14、静态数据结构和动态数据结构_静态结构和动态结构-程序员宅基地

线性表(list)的表现形式:零个或多个数据元素组成的集合,数据元素在位置上是有序列的,数据元素的个数是有限的,数据元素的类型必须相同。

线性表的抽象定义:线性表是具有相同类型的n个数据元素的有限序列,每一个叫表项,n是表长度

纯虚函数的作用:为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。在很多情况下,基类本身生成对象是不合理的,例如,动物作为一个基类派生出老虎狮子等,但动物本身生成对象不合理。为了解决上述问题,引入纯虚函数的概念,将函数定义为纯虚函数,则编译器要求再派生类中必须予以重写以实现多态性,同时含有纯虚函数的类称为抽象类,它不能生成对象。这样就很好的解决了上述两个问题。

//模板的方式描述线性表,不要List.cpp
#ifndef LIST_H_
#define LIST_H_
#include "Wobject.h"
namespace WSlib
{
template <typename T>
class List:public Wobject
{
public:
virtual bool insert(int i,const T& e)=0;
virtual bool remove(int i)=0;
virtual bool set(int i,const T& e)=0;
virtual bool get(int i,T& e)=0;
virtual int length()const =0;
virtual void clear()=0;
};
}
#endif
//线性表是数据元素的有序并且有限的集合,线性表中的数据元素必须是类型相同的,可用于描述排队关系的问题
//线性表在c++中表现为一个抽象类
//线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表中的数据元素
//可以用一维数组来实现顺序存储结构,存储空间:T* m_array: 当前长度:int m_length;
//顺序存储结构的元素获取操作:判断目标位置是否合法,将目标位置作为数组下标获取元素
//顺序表的插入操作:1、判断目标位置是否合法2、将目标位置之后的所有元素后移一个位置3、将新元素插入目标位置4、线性表长度加1
//顺序存储结构的元素删除操作:1、判断目标位置是否合法2、将目标位置后的所有元素前移一个位置3、将线性表长度减一
//完成顺序存储结构线性表SeqList的抽象实现,设计要点:

//抽象类模板,存储空间的位置和大小由子类完成,实现顺序存储结构线性表的关键操作(增,删,查),提供数组操作符,快速访问数据

#ifndef SEQLIST_H_
#define SEQLIST_H_
#include "List.h"
#include "Exception.h"
namespace WSlib
{
template<typename T>
class SeqList:public List<T>
{
protected:
T* m_array;  //顺序存储空间
T m_length;  //当前线性表长度
public:
bool insert(int i,const T& e)
{
bool ret=((0<=i)&&(i<=m_length)); //注意这里是《=  而之后的是<
ret=ret&&(m_length<capacity());
if(ret)
{
for(int p=m_length-1;p>=i;p--)
{
m_array[p+1]=m_array[p];
}
m_array[i]=e;
m_length++;
}
return ret;
}
bool remove(int i)
{
bool ret=((0<=i)&&(i<m_length));
if(ret)
{
for(int p=i;p<m_length-1;p++)
{
m_array[p]=m_array[p+1];
}
m_length--;
}
return(ret);

}
bool set(int i,const T& e)
{
bool ret=((i>=0)&&(i<m_length));
if(ret)
{
m_array[i]=e;
}
return ret;
}
bool get(int i,T& e)
{
bool ret=((i>=0)&&(i<m_length));
if(ret)
{
e=m_array[i];
}
return ret;
}
    int length()const 
{
return m_length;
}


    void clear()
{
m_length=0;
}
//顺序存储线性表的数组访问方式
T& operator[](int i)
{
if((0<=i)&&(i<m_length))   //没有等于 mmp
{
return m_array[i];
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException, "parameter is invald....");
}
}


/* T& operator[](int i) const
{
return (const_cast<SeqList<T>&>(*this))[i];
//return (*this)[i];
}*/
//顺序存储空间的容量
virtual int capacity()const=0;  //获取最大容量,纯虚函数交给子类完成
};
}
#endif
/********************************************************************************
#include<iostream>
#include"SeqList.h"
using namespace std;
using namespace WSlib;

int main()
{
SeqList<int>* l;

return 0;
}

**********************************************************************************/

//SeqList仅仅把关键的操作实现了,顺序存储空间的指定在它的子类实现
//思考StaticList和Dynaminlist如何实现,差异在哪里?
//StaticList设计要点:类模板,使用原生数组作为顺序存储空间,使用模板参数决定数组大小
#ifndef STATICLIST_H_
#define STATICLIST_H_
#include "SeqList.h"
namespace WSlib
{
template <typename T,int N>
class StaticList:public SeqList<T>
{
protected:
T m_space[N]; //顺序存储空间,N为模板参数
public:
StaticList()     //指定父类成员的初始值
{
this->m_array=m_space; //this->m_array=m_space;
this->m_length=0;      //this->m_length=0;
}
int capacity() const   //成员函数需要考虑一下是否是const属性
{
return N;
}
};
}
#endif
/*************************************************************************
#include<iostream>
#include"StaticList.h"
using namespace std;
using namespace WSlib;

int main()
{
StaticList<int,5> l;
for(int i=0;i<l.capacity();i++)
{
l.insert(0,i);
}
for(int i=0;i<l.length();i++)
{
cout<<l[i]<<endl;
}
l[0]*=l[0];
for(int i=0;i<l.length();i++)
{
cout<<l[i]<<endl;
}
try
{    
  l[5]=5;
}
catch(const Exception&e)
{
cout<<e.message()<<endl;
cout<<e.location()<<endl;
}
return 0;
}

*************************************************************************/

/*
设计要点:类模板
申请连续堆空间作为顺序存储空间,动态设置顺序存储空间的大小,保证重置顺序存储空间时的异常安全性
函数异常安全的概念:不泄漏任何资源,不允许破坏数据。
函数异常安全的基本保证:如果异常被抛出,对象内的任何成员任然能保持有效状态,没有数据的破坏及资源泄漏
*/
#ifndef DYNAMICLIST_H_
#define DYNAMICLIST_H_
#include "SeqList.h"
namespace WSlib
{
template <typename T>
class DynamicList:public SeqList<T>
{
protected:
int m_capacity; //顺序存储空间的大小
public:
DynamicList(int capacity)//申请空间
{
this->m_array=new T[capacity];
if(this->m_array!=NULL)
{
this->m_length=0;
this->m_capacity=capacity;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"no memory to create dynamiclist object...");
}

}
int capacity() const
{
return m_capacity;
}
//重新设置顺序存储空间的大小
void resize(int capacity)
{
if(m_capacity!=capacity)
{
T* array=new T[capacity];
if(array!=NULL)
{
int length=(this->m_length<capacity? this->m_length:capacity);
for(int i=0;i<length;i++)
{
array[i]=this->m_array[i];
}
T* temp=this->m_array;
this->m_array=array;
this->m_length=length;
this->m_capacity=capacity;
delete[] temp;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"no memory to create dynamiclist object");
}
}
/*我们要重置空间大小,但是之前的数据不能丢失,如果之前是5,resize为3,前三个数据要保留下来,
m_array指向之前的空间,delete的时候可能调用析构函数的调用,因为泛指类型,如果是类类型抛出一个异常,
函数异常返回,则下面的赋值操作无法执行,不是异常安全的,先用temp指向之前的空间,3条赋值语句不会发生异常,
然后在delete,即使发生异常,赋值已经完成,还是可以用的,for循环里边的赋值操作有可能发生异常,泛指类型T导致的,交由第三方工程师处理*/
}
~DynamicList() //归还空间
{
delete[] this->m_array;
}
};
}

#endif

/*************************************************************************************************************
#include<iostream>
#include"DynamicList.h"
using namespace std;
using namespace WSlib;
int main()
{
DynamicList<int> l(5);
for(int i=0;i<l.capacity();i++)
{
l.insert(0,i);
}
for(int i=0;i<l.length();i++)
{
cout<<l[i]<<endl;
}
l[0]*=l[0];
for(int i=0;i<l.length();i++)
{
cout<<l[i]<<endl;
}
try
{    
  l[5]=5;
}
catch(const Exception&e)
{
cout<<e.message()<<endl;
cout<<e.location()<<endl;
l.resize(10);
l.insert(5,50);
}
l[5]=5;
for(int i=0;i<l.length();i++)
{
cout<<l[i]<<endl;
}
l.resize(3);
for(int i=0;i<l.length();i++)
{
cout<<l[i]<<endl;
}
return 0;
}
//是否可以将dynamiclist作为staticlist的子类实现,不能,反之也不能,两个类对顺序存储空间的指定是截然不同的,
//没有关系,所以在类层次结构的地位是平等的。staticlist通过模板参数定义顺序存储空间,
//dynamiclist通过动态内存申请定义顺序存储空间,支持动态重置顺序存储空间的大小,resize的实现需要保证异常安全
*************************************************************************************************************/

静态数据结构,例如数组在内存中是连续的存储区域,缺点是长度是固定的,新增或删除某一数据花费的时间比较多。优点可以直接访问各个数据,各个数据的地址都可以根据首地址得到,访问时间复杂度O(1)。

动态数据结构,例如链表在内存中不是连续的存储区域,每一个节点包含节点数据和下一个节点的指针。缺点是不利于节点的随机访问。访问节点花费时间比较多,为O(n)。优点是能够动态的调整容量,插入或者删除数据方便。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/WS857707645/article/details/80141853

智能推荐

5个超厉害的资源搜索网站,每一款都可以让你的资源满满!_最全资源搜索引擎-程序员宅基地

文章浏览阅读1.6w次,点赞8次,收藏41次。生活中我们无时不刻不都要在网站搜索资源,但就是缺少一个趁手的资源搜索网站,如果有一个比较好的资源搜索网站可以帮助我们节省一大半时间!今天小编在这里为大家分享5款超厉害的资源搜索网站,每一款都可以让你的资源丰富精彩!网盘传奇一款最有效的网盘资源搜索网站你还在为找网站里面的资源而烦恼找不到什么合适的工具而烦恼吗?这款网站传奇网站汇聚了4853w个资源,并且它每一天都会持续更新资源;..._最全资源搜索引擎

Book类的设计(Java)_6-1 book类的设计java-程序员宅基地

文章浏览阅读4.5k次,点赞5次,收藏18次。阅读测试程序,设计一个Book类。函数接口定义:class Book{}该类有 四个私有属性 分别是 书籍名称、 价格、 作者、 出版年份,以及相应的set 与get方法;该类有一个含有四个参数的构造方法,这四个参数依次是 书籍名称、 价格、 作者、 出版年份 。裁判测试程序样例:import java.util.*;public class Main { public static void main(String[] args) { List <Book>_6-1 book类的设计java

基于微信小程序的校园导航小程序设计与实现_校园导航微信小程序系统的设计与实现-程序员宅基地

文章浏览阅读613次,点赞28次,收藏27次。相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低学校的运营人员成本,实现了校园导航的标准化、制度化、程序化的管理,有效地防止了校园导航的随意管理,提高了信息的处理速度和精确度,能够及时、准确地查询和修正建筑速看等信息。课题主要采用微信小程序、SpringBoot架构技术,前端以小程序页面呈现给学生,结合后台java语言使页面更加完善,后台使用MySQL数据库进行数据存储。微信小程序主要包括学生信息、校园简介、建筑速看、系统信息等功能,从而实现智能化的管理方式,提高工作效率。

有状态和无状态登录

传统上用户登陆状态会以 Session 的形式保存在服务器上,而 Session ID 则保存在前端的 Cookie 中;而使用 JWT 以后,用户的认证信息将会以 Token 的形式保存在前端,服务器不需要保存任何的用户状态,这也就是为什么 JWT 被称为无状态登陆的原因,无状态登陆最大的优势就是完美支持分布式部署,可以使用一个 Token 发送给不同的服务器,而所有的服务器都会返回同样的结果。有状态和无状态最大的区别就是服务端会不会保存客户端的信息。

九大角度全方位对比Android、iOS开发_ios 开发角度-程序员宅基地

文章浏览阅读784次。发表于10小时前| 2674次阅读| 来源TechCrunch| 19 条评论| 作者Jon EvansiOSAndroid应用开发产品编程语言JavaObjective-C摘要:即便Android市场份额已经超过80%,对于开发者来说,使用哪一个平台做开发仍然很难选择。本文从开发环境、配置、UX设计、语言、API、网络、分享、碎片化、发布等九个方面把Android和iOS_ios 开发角度

搜索引擎的发展历史

搜索引擎的发展历史可以追溯到20世纪90年代初,随着互联网的快速发展和信息量的急剧增加,人们开始感受到了获取和管理信息的挑战。这些阶段展示了搜索引擎在技术和商业模式上的不断演进,以满足用户对信息获取的不断增长的需求。

随便推点

控制对象的特性_控制对象特性-程序员宅基地

文章浏览阅读990次。对象特性是指控制对象的输出参数和输入参数之间的相互作用规律。放大系数K描述控制对象特性的静态特性参数。它的意义是:输出量的变化量和输入量的变化量之比。时间常数T当输入量发生变化后,所引起输出量变化的快慢。(动态参数) ..._控制对象特性

FRP搭建内网穿透(亲测有效)_locyanfrp-程序员宅基地

文章浏览阅读5.7w次,点赞50次,收藏276次。FRP搭建内网穿透1.概述:frp可以通过有公网IP的的服务器将内网的主机暴露给互联网,从而实现通过外网能直接访问到内网主机;frp有服务端和客户端,服务端需要装在有公网ip的服务器上,客户端装在内网主机上。2.简单的图解:3.准备工作:1.一个域名(www.test.xyz)2.一台有公网IP的服务器(阿里云、腾讯云等都行)3.一台内网主机4.下载frp,选择适合的版本下载解压如下:我这里服务器端和客户端都放在了/usr/local/frp/目录下4.执行命令# 服务器端给执_locyanfrp

UVA 12534 - Binary Matrix 2 (网络流‘最小费用最大流’ZKW)_uva12534-程序员宅基地

文章浏览阅读687次。题目:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=93745#problem/A题意:给出r*c的01矩阵,可以翻转格子使得0表成1,1变成0,求出最小的步数使得每一行中1的个数相等,每一列中1的个数相等。思路:网络流。容量可以保证每一行和每一列的1的个数相等,费用可以算出最小步数。行向列建边,如果该格子是_uva12534

免费SSL证书_csdn alphassl免费申请-程序员宅基地

文章浏览阅读504次。1、Let's Encrypt 90天,支持泛域名2、Buypass:https://www.buypass.com/ssl/resources/go-ssl-technical-specification6个月,单域名3、AlwaysOnSLL:https://alwaysonssl.com/ 1年,单域名 可参考蜗牛(wn789)4、TrustAsia5、Alpha..._csdn alphassl免费申请

测试算法的性能(以选择排序为例)_算法性能测试-程序员宅基地

文章浏览阅读1.6k次。测试算法的性能 很多时候我们需要对算法的性能进行测试,最简单的方式是看算法在特定的数据集上的执行时间,简单的测试算法性能的函数实现见testSort()。【思想】:用clock_t计算某排序算法所需的时间,(endTime - startTime)/ CLOCKS_PER_SEC来表示执行了多少秒。【关于宏CLOCKS_PER_SEC】:以下摘自百度百科,“CLOCKS_PE_算法性能测试

Lane Detection_lanedetectionlite-程序员宅基地

文章浏览阅读1.2k次。fromhttps://towardsdatascience.com/finding-lane-lines-simple-pipeline-for-lane-detection-d02b62e7572bIdentifying lanes of the road is very common task that human driver performs. This is important ..._lanedetectionlite

推荐文章

热门文章

相关标签