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

智能推荐

Vue2切换生产环境、测试环境和开发环境_vue2+ts切换测试环境和开发环境-程序员宅基地

文章浏览阅读1w次,点赞10次,收藏48次。  最近小咸儿一直在学习有关Vue的东西,所以将最近在弄得东西总结下来,以供参考。  Vue配置环境变量和模式,可以分为两种模式:  第一种:Vue项目搭建成功后,config和build文件夹都存在​​​​  知道有这两个文件夹后,接下来就该配置环境变量以及对应的模式了。  首先,看一下package.json中配置的启动方式:  从中,可以看出使用npm run dev启动项目时..._vue2+ts切换测试环境和开发环境

[ Linux Audio 篇 ] Linux Audio 子系统资料集锦_pulseaudio等同于linux中的什么audio-程序员宅基地

文章浏览阅读746次,点赞2次,收藏6次。最近需要准备Linux Audio 相关的PPT,于是将以往的知识点和遇到的问题进行整理和梳理,以便向大家讲解。_pulseaudio等同于linux中的什么audio

【语音】用 C# 开发自己的语音识别程序_ai算法开发 c#-程序员宅基地

文章浏览阅读5.4k次,点赞2次,收藏34次。开发工具:vs 2017AI 平台:http://ai.baidu.com/准备工作1、注册百度账号2、登录百度 AI 开发平台,http://ai.baidu.com/3、在控制台点击“百度语音”服务,点击“创建应用”,填写必填项,勾选额外接口,点击立即创建获取秘钥。在应用列表中查看自己的id用 360 软件管家安装 vs2017创建自己的项目1、新建项目打开 vs2017..._ai算法开发 c#

品优购项目--列表页 list._品优购手机列表页思路-程序员宅基地

文章浏览阅读4.8k次,点赞2次,收藏14次。效果图HTML部分 list.html&lt;!DOCTYPE html&gt;&lt;html lang="zh-CN"&gt;&lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;title&gt;列表页-手机页面!&lt;/title&gt; &lt;meta name="description&_品优购手机列表页思路

跨模态检索论文阅读:(PTP)Position-guided Text Prompt for Vision-Language Pre-training_图像-文本检索中tr是什么指标-程序员宅基地

文章浏览阅读1.5k次,点赞4次,收藏6次。在这项工作中,我们提出了一种新的位置引导的文本提示(PTP)范式,以提高用VLP训练的跨模态模型的视觉定位能力。具体来说,在VLP阶段,PTP将图像分为N×N块,并通过VLP中广泛使用的目标检测器识别每个块中的目标。然后,它通过鼓励模型预测给定区块中的目标或重新定义给定目标的区块,将视觉定位任务重新表述为给定PTP的填空问题,例如,在PTP中填写"[P]“或”[O]",“区块[P]中有一个[O]”。 这种机制提高了VLP模型的视觉定位能力,从而帮助它们更好地处理各种下游任务。_图像-文本检索中tr是什么指标

数据库领域的四位图灵奖得主及启示_数据库领域的代表人物及其贡献-程序员宅基地

文章浏览阅读4.7k次,点赞5次,收藏15次。图灵奖最早设立于1966年,是美国计算机协会在计算机技术方面所授予的最高奖项,被喻为计算机界的诺贝尔奖。它是以英国数学天才Alan Turing先生的名字命名的,Alan Turing先生对早期计算的理论和实践做出了突出的贡献。图灵奖主要授予在计算机技术领域做出突出贡献的个人。图灵奖主要授予在计算机技术领域做出突出贡献的个人。而这些贡献必须对计算机技术有长远而重要的影响。目录Charles ..._数据库领域的代表人物及其贡献

随便推点

sql中count计数为null的时候返回0_sql统计count为空输出0-程序员宅基地

文章浏览阅读4.1k次。sql的IFNULL用法_sql统计count为空输出0

Simulink MBD技术支持下的新能源电动汽车主驱电驱控制器算法模型与开发资料:量产模型、软件、代码、架构设计及测试资料(全套)-程序员宅基地

文章浏览阅读341次,点赞3次,收藏7次。在Simulink中,用户可以通过拖拽和连接各种模块来建立系统模型,并使用Matlab/Simulink提供的丰富库中的功能模块进行建模。同时,Simulink提供了代码生成功能,可以将模型直接转换为C代码,供嵌入式系统使用。通过图形化建模,开发人员可以更好地理解系统的结构和行为,并且可以在系统级别上进行模拟和测试,以验证算法的准确性和性能。主机厂基于Simulink MBD新能源电动汽车主驱电驱控制器算法模型及开发资料,量产模型,量产软件,量产代码,软件架构设计,输入输出定子,单元测试,MIL测试资料。

Windows 服务(附服务开发辅助工具)_windows创建服务工具-程序员宅基地

文章浏览阅读572次。引子 近来在 Windows 下摆弄了一阵子的服务程序,有在 C++ 下弄服务的,也在 C# 下弄服务的,感觉在 C# 下弄服务蛮简单的の,C/C++ 的麻烦蛮多の(当然我的服务所要求的功能也是很简单的,就启动个进程),只不过服务在安装啊、调试啊、卸载啊上面麻烦的要死,弄得我烦躁起来了,而且对于服务的安装和卸载中间还有一个小插曲的,因为我很早_windows创建服务工具

国家助推科技企业发展有关政策分析 -- 杨跃承-程序员宅基地

文章浏览阅读475次。杨跃承老师作为盛景网联科技的高级合伙人,同时也是多家研究院的研究员,对科技企业的理解非常深入,只碍于时间限制,只介绍了其中核心的一部分的内容。。。_杨跃承

Android问题解决01_android 问题解决汇总-程序员宅基地

文章浏览阅读126次。转载:问题解决最近更新了SDK后每次打开eclipse都会报错,错误如下:sdk\system-images\android-23\android-wear\armeabi-v7a\devices.xmlcvc-complex-type.2.4.d: 发现了以元素 'd:skin' 开头的无效内容。此处不应含有子元素。点击OK后虽然不影响使用,但看着错误不解决总感觉不舒服,于是决定解决..._android 问题解决汇总

更改sqlserver服务器排序规则_查sqlsysadminaccounts-程序员宅基地

文章浏览阅读2.5k次。输入SELECT SERVERPROPERTY('collation') 查询当前服务器规则然后windows+r 输入services.msc关闭sqlserver服务打开cmd命令窗口找到sqlserver的安装位置(c盘)cdC:\Program Files\Microsoft SQL Server\120\Setup Bootstrap\SQLServer2014 命令 跳转到安装位置输入Setup /QUIET /ACTION=REBUILDD..._查sqlsysadminaccounts