什么是线性表?
线性表简称表,是n(n>=0)个具有相同类型的数据元素的有限序列,线性表中数据元素的个数称为线性表的长度,长度为0的表称为空表。
什么是顺序表?
线性表的顺序存储结构称为顺序表。
顺序表是用一段地址连续的存储单元依次存储线性表的数据元素,因为线性表中每个元素的类型相同,通常用一维数组来实现线性表,也就是把线性表中相邻的元素存在数组中相邻的位置(即用物理位置来表现元素间的关系)。
顺序表的必要属性:
1.存储空间的起始位置 。顺序表是连续存储,只要确定了存储顺序表的起始地址,就可以计算任何一个元素的存储地址。并且,计算任何一个元素的存储地址的时间是相等的(单个元素所占的空间*该元素的序号+起始位置),具有这一特点的存储结构也称为随机存取(时间性能O(1) )结构。
2.顺序表的容量(最大长度MaxSize)。用数组存储顺序表,就意味着要分配固定长度的数组空间,因此必须确定数组的长度,即存放线性表的数组空间的长度。
3.顺序表的当前长度(length)。因为在线性表中可以进行插入操作,则数组的长度就要大于当前线性表的长度。即需要知道顺序表的当前长度(length),以及最大长度(MaxSize)。
顺序表的存储要点:
1.分配一段地址连续的存储空间
2.依次存储线性表中的数据元素
3.表示逻辑关系不分配存储空间(最本质)(元素之间的位置关系即表示其逻辑关系)
由于线性表的数据元素类型不确定,所有采用C++的模板机制。
对C++模板机制不太了解的可以看看我之前的-----》C++模板的概念 定义和使用
Seqlist.h:(顺序表类的声明)
const int MaxSize=100; //100只是示例性的数据,可以根据实际问题具体定义
template //定义模板类SeqList
class SeqList
{
public:
SeqList( ); //无参构造函数
SeqList(T a[], int n); //有参构造函数
~SeqList(); //析构函数为空
int Length(); //求线性表的长度
T Get(int i); //按位查找,取线性表的第i个元素
int Locate(T x); //按值查找,求线性表中值为x的元素序号
void Insert(int i, T x); //在线性表中第i个位置插入值为x的元素
T Delete(int i); //删除线性表的第i个元素
void PrintList(); //遍历线性表,按序号依次输出各元素
private:
T data[MaxSize]; //存放数据元素的数组
int length; //线性表的长度
};
基本操作的算法:
1.构造函数
(1) 无参构造函数 SeqList( ):
创建一个空的顺序表,只需简单的将顺序表的长度length初始化为0。
template
SeqLsit::SeqList()
{
length=0;
}
(2) 有参构造函数 SeqList(T a[], int n) :
创建一个长度为n的顺序表,需要将给定的数组元素作为线性表的数据元素传入顺序表中,并将传入的元素个数作为顺序表的长度。
template
SeqList::SeqList(T a[],int n)
{
if(n>MaxSize) throw "参数超过最大限度";
for(int i=0; i
2.求线性表的长度
int Length() 只需返回成员变量length的值
template
int SeqList::Length()
{
return length;
}
3.查找操作:
(1) 按位查找
T Get(int i)取线性表的第i个元素:
顺序表中第i个元素存储在数组中下标为i-1的位置,所以,容易实现按位查找。该按位查找算法的时间复杂度为O(1)。
template
T SeqList::Get(int i)
{
if(i<1 && i>length)
throw"查找位置超出边界";
else
return data[i-1];
}
(2) 按值查找
int Locate(T x) 求线性表中值为x的元素序号:
在顺序表中实现按值查找操作,需要对顺序表中的元素依次进行比较。如果查找成功,返回元素的序号(注意不是下标);如果查找不成功,返回查找失败的标准‘0’。
template
int SeqList::Locate(T x)
{
for (int i=0; i
按值查找算法的问题规模是表长n,最好的情况是比较一次就行了,最坏情况是比较n次,假设数据是等概率分布,则平均比较表长的一半。所以,按值查找算法的平均时间性能是O(n)。
4.插入操作
void Insert(int i, T x) 在线性表中第i个位置插入值为x的元素:
其伪代码如下(注意需要考虑的情况):
伪代码:
1.如果表满了,则抛出上溢异常;
2.如果元素的插入位置不合理,则抛出位置异常;
3.将最后一个元素直至第i个元素分别向后移动一个位置;
4.将元素x填入位置i处;
5.表长加1;
C++描述如下:
template
void SeqList::Insert(int i, T x)
{
int j;
if (length>=MaxSize) throw "插入位置超过最大限制";
if (i<1 || i>length+1) throw "插入位置有误";
for (j=length; j>=i; j--)
data[j]=data[j-1]; //注意第j个元素存在数组下标为j-1处
data[i-1]=x;
length++;
}
在第i(1<= i <= i+1)个位置上插入一个元素后移语句的执行次数为n-i+1,假设在表中任何位置上插入元素的机会是均等的,则平均后移语句的执行次数为n/2,算法的时间复杂度为O(n)。
5.顺序表删除算法
T Delete(int i) 删除线性表的第i个元素:
删除操作是将表的第i个元素删除,使长度为n的线性表变成长度为n-1的线性表,取出被删除元素后,必须从第i+1(下标为i)个元素开始移动,直至将最后一个元素前移为止。
伪代码:
1.如果表空,则抛出空表警告;
2.如果删除位置不合理,则抛出删除位置异常;
3.取出被删除元素;
4.将下标为i,i+1,...,n-1处的元素分别移到下标i-1,i,...,n-2处;
5.表长减1,返回被删元素值;
C++描述如下:
template
T SeqList::Delete(int i)
{
if(length==0)
throw"表为空!";
if(i<1||i>length)
throw"位置异常";
x=data[i-1]; //取出位置i的元素
for(j=i;j
在顺序表上实现删除操作,等概率情况下,平均要移动表中一半的元素,算法的平均时间复杂度为O(n)。
6.遍历操作:
void PrintList() 按下标依次输出各元素:
template
void SeqList::PrintList()
{
for(int i=0;i
最后:
顺序表的优点:
1.无需为表示表中的元素之间的逻辑关系而增加额外的存储空间。
2.随机存取:可以快速的存取表中任一位置的元素。
顺序表的缺点:
1.插入和删除操作需要移动大量元素。
2.表的容量难以确定,表的容量难以扩充。
3.造成存储空间的碎片
参考至-----《数据结构(C++版)(第二版)》/王红梅,胡明,王涛编著.