一.前言
如果一个数据结构的逻辑结构是线性表,而物理结构是顺序存储,那么这个数据结构就是一个顺序表。换而言之,使用顺序存储的线性表就是顺序表。
二.顺序表
2.1顺序表的可视化
如下图为顺序表在内存空间中的存储结构:
·顺序表将所有元素按照顺序存放在相邻位置,所以可以随时找到第i个位置的元素,所以顺序表支持随机存取。
2.2顺序表的定义
2.2.1静态分配
顺序表的存储有静态分配和动态分配两种方式。静态分配是用一个数组来表示顺序表,因为数组的大小不变,所以叫静态分配。定义代码如下:
#define MaxSize 10
typedef struct
{
Elemtype data[MaxSize];
int Length;
}SqList;
代码直接向计算机申请了长度为Maxsize*sizeof(Elemtype)的内存的数组作为顺序表的元素存储空间,同时申请了一个整型变量Length来记录当前顺序表长度。(PS:Elemtype指的是你想要使用的元素类型,可以是整型变量、浮点型等)。
2.2.2动态分配
动态分配相比静态分配,能够更好的适应项目所需的内存大小,不需要一开始就分配好所需的全部内存。它的定义代码如下:
#define InitSize 100
typedef struct
{
Elemtype *data;
int Length,MaxSize;
}SeqList;
动态分配定义了Length来记录当前顺序表的长度,MaxSize来记录当前设定的顺序表最大长度。并且申请了一个指针来指向顺序表的数据域表头。
2.3顺序表的初始化
2.3.1静态分配的初始化
下面是静态分配的初始化代码:
void InitList(SqList &L)
{
/* for(int i=0;i<MaxSize;i++)
{
L.data[i]=0;
}*/
L.Length=0;
}
先将顺序表L传入函数中,然后将顺序表中所有元素设为0(表示为空,还有一个目的是防止有脏数据,这一步可做可不做),随后将Length设为0表示为空表即可。
2.3.2动态分配的初始化
下面是动态分配初始化代码:
void InitList(SeqList &L)
{
L.data=(Elemtype*)malloc(sizeof(Elemtype)*InitSize);
L.Length=0;
L.MaxSize=InitSize;
}
这段代码首先申请了一段连续的内存,内存大小为InitSize个Elemtype的大小,malloc函数的能够申请内存,而前面的(Elemtype*)是为了将空间强转为元素所需的空间类型。
随后将MaxSize设置为InitSize,将Length设置为0就结束了。
2.4顺序表的销毁
如果我们不再使用一个顺序表,那么我们会将其销毁。当然,如果是使用数组的静态分配,计算机会自动释放其内存空间。但是如果是动态分配申请的内存,那么计算机将无法自动释放空间。下面是销毁的代码:
void DestroyList(SeqList &L)
{
L.Length=0;
Free(L.data);
}
2.5顺序表的扩容
在这里静态表不做讨论,因为它的大小固定无法改变。下面是对动态分配顺序表扩容的代码:
void AddSize(SeqList &L, int n)
{
Elemtype *a=L.data;
L.data=(Elemtype*)malloc((n+L.MaxSize)*sizeof(Elemtype));
L.MaxSize=n+L.MaxSize;
for(int i=0;i<L.Length;i++)
{
L.data[i]=a[i];
}
free(a);
}
这里我们重新申请一片内存空间,然后把数据搬到新空间中,再释放原空间即可。
2.6顺序表查询对应元素
如果我们要在顺序表中查询一个特定的元素,并返回它的位置,代码如下:
int LocateElem(SeqList L, Elemtype e)
{
for(int i=0;i<L.Length;i++)
{
if(L.data[i]==e)
{
return i;
}
}
printf(“没有找到”);
return -1;
}
2.7查询第i个位置顺序表的元素
因为顺序表支持随机存取,所以这个算法时间复杂度为O(1):
Elemtype GetElem(SeqList L, int i)
{
if(i<0||i>L.Length-1)
{
printf(“位次不合法”);
return ;
}
return L.data[i];
}
2.8在顺序表中插入元素
如果要在顺序表中插入一个元素,代码如下:
bool ListInsert(SeqList &L, Elemtype e, int i)
{
if(L.Length==L.MaxSize)
{
printf(“顺序表满,无法插入”);
return false;
}
for(int j=L.Length-1;j>=i;j--)
{
L.data[j+1]=L.data[j];
}
L.data[i]=e;
L.Length+=1;
return true;
}
这个算法的最好情况是插在表尾,只需要执行一次代码;最差是插在表头,需要执行n次。因此它的时间复杂度为O(n)。
2.9删除顺序表中元素
如果我们要删除顺序表中指定位置的元素,并返回其值,代码为:
bool ListDelet(SeqList &L, Elemtype &e, int i)
{
if(i>L.Length-1||i<0)
{
printf(“位次非法”);
return false;
}
e=L.data[i];
for(int j=i;j<L.Length-1;j++)
{
L.data[j]=L.data[j+1];
}
L.Length-=1;
return true;
}