
数据结构C++语言实现--线性表概念及顺序存储结构
前言
数据结构C++语言实现的最终目标是要打造一个可复用的数据结构库,具体将从基础设施、数据结构、算法三个方面展开。代码实现在智能指针、异常类、顶层父类三大基础类上进行代码实现。本文介绍线性表的顺序存储结构的概念及抽象实现。
正文
1.线性表的本质和操作
线性表(List)的表现形式
--零个或多个数据元素组合的集合
--数据元素在位置上是有序排列的
--数据元素的个数是有限的
--数据元素的类型必须相同
2.线性表(List)的抽象定义
线性表是具有相同类型的n(n≥0)个数据元素的有限序列: (a0, a1, ...,an-1)ai是表项(数据元素),n是表长度。
3.线性表(List)的性质
-- a0为线性表的第一个元素,只有一个后继
-- an-1为线性表的最后一个元素,只有一个前驱
-- 除a0和an-1外的其他元素ai,既有前驱,又有后继
-- 直接支持逐项访问和顺序存取
4.线性表的一些常用操作
-- 将元素插入线性表
-- 将元素从线性表中删除
-- 获取目标位置处元素的值
-- 设置目标位置处元素的值
-- 获取线性表的长度
-- 清空线性表
5.线性表抽象类的创建(List.h)
List.h
/*===========================================================
* 文件:线性表-抽象类
* 日期:
* 设计人:
*
* 线性表的定义:线性表是具有相同类型的n(>=0)个数据元素的有限序列
* ========================================================*/
#ifndef LIST_H
#define LIST_H
#include "Object.h"
namespace DataStructLib {
template<typename T>
class List:public Object
{
protected:
List(const List&);
List& operator=(const List&);
public:
List() {}
virtual bool insert(const T& e)=0;
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) const = 0;
virtual int find(const T& e) const = 0;
virtual int length() const = 0;
virtual void clear() = 0;
};
}
#endif // LIST_H
List类设置为抽象类(不能实例化--不能定义对象)是用来继承的,我们可以定义List类的指针来测试我们的代码。
6.线性表概念小结
-- 线性表是数据元素的有序并且有限的集合
-- 线性表的数据元素必须是类型相同的
-- 线性表可用于描述排队关系的问题
-- 线性表在程序中表现为一种特殊的数据类型
-- 线性表在C++中表现为一个抽象类
7.线性表顺序存储的定义
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表中的数据元素。
8.设计思路
可以用一维数组来实现顺序存储结构
存储空间:T* m_array;
当前长度:int m_length;
9.顺序存储结构的元素获取操作
-- 判断目标位置是否合法
-- 将目标位置作为数组下标获取元素
10.顺序存储结构的元素插入操作
1)判断目标位置是否合法
2)将目标位置之后的所有元素后移一个位置
3)将新元素插入目标位置
4)线性表长度加1
11.顺序存储结构的元素删除操作
1)判断目标位置是否合法
2)将目标位置后的所有元素前移一个位置
3)线性表长度减一
12.顺序存储结构线性表的抽象实现
线性表的顺序存储结构抽象类SeqList继承自List,线性表的顺序存储结构的静态实现StaticList类和动态实现DynamicList类继承自SeqList,为什么StaticList和DynamicList不直接继承自List了?
因为,线性表有顺序存储结构就会有链式存储结构,所以有顺序存储结构的抽象实现就会有链式结构的抽象实现,也就是说List抽象了顺序表,SeqList抽象了顺序存储结构,后面还会有抽象了链式存储结构的LinkList继承自List。
SeqList设计要点
-- 抽象类模板,存储空间的位置和大小由子类完成
-- 实现顺序存储结构线性表的关键操作(增,删,查,等)
-- 提供数据操作符,方便快速获取元素
13.线性表顺序存储结构抽象类的创建(SeqList.h)
SeqList.h/*===========================================================
* 文件:顺序存储结构线性表的抽象实现
* 日期:
* 设计人:
*
* 1.抽象类模板,存储空间的位置和大小由子类完成
* 2.实现顺序存储结构的关键操作(增减 删除 插入操作等)
* 3.提供数组操作符,方便快速获取元素
* ========================================================*/
#ifndef SEQLIST_H
#define SEQLIST_H
#include "List.h"
#include "Exception.h"
namespace DataStructLib {
template<typename T>
class SeqList:public List<T>
{
protected:
T* m_array;
int m_length;
public:
bool insert(const T& e)
{
return insert(m_length,e);
}
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 = ((0 <= i) && (i < m_length));
if( ret )
{
m_array[i] = e;
}
return ret;
}
bool get(int i,T& e) const
{
bool ret = ((0 <= i) && (i < m_length));
if( ret )
{
e = m_array[i];
}
return ret;
}
int find(const T& e) const
{
int ret = -1;
for(int i=0; i<m_length; i++)
{
if(m_array[i] == e)
{
ret = i;
break;
}
}
return ret;
}
int length() const
{
return m_length;
}
void clear()
{
m_length = 0;
}
T& operator[](int i)
{
bool ret = ((0 <= i) && (i < m_length));
if( ret )
{
return m_array[i];
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException,"Parameter i is invalid...");
}
}
T operator [](int i)const
{
return const_cast<T&>(*this)[i];
}
virtual int capacity() const = 0;
};
}
#endif // SEQLIST_H
SeqList类设置为抽象类(不能实例化--不能定义对象)是用来继承的,我们可以定义SeqList类的指针来测试我们的代码。
Note: 数据结构实践系列文章中用到了非常多的C++和C语言知识,数据结构系列文章中不再重复讲解,具体可以参考本公众号中C/C++系列文章。
参考资料:《C++ primer》
《C++对象模型》
狄泰软件学院唐佐林老师课程
推荐阅读
Autosar架构下的模块详细设计及代码实现--基于配置的编程方法
AUTOSAR CAN通信协议栈分析(2)-CanIf
CANoe工具使用(1)-实现CAN通道的收、发、录、回放报文
文章转载自公众号:汽车电子嵌入式
