什么是顺序表?
顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。 (源于百度百科)
用一张图来表示这种数据结构:
顺序表:就是用一段连续的存储单元一次存储数据元素的线性结构
地址连续的空间,一般情况下采用数组,但数组有静态数组和动态数组,因此,顺序表也分为静态顺序表和动态顺序表
静态数组:
对于静态顺序表这种数据结构,我们定义它的时候结构体里需要有两个字段:
1.整个数组的大小
2.顺序表中有效元素的个数
下来,我们就来具体在代码中了解一下静态顺序表的基本操作
结构体的定义:
typedef struct SeqList{
DataType array[MAX_SIZE]; //整个数组的大小
int size; //顺序表中有效元素的个数
} SeqList;
初始化、销毁
void SeqListInit(SeqList *pSL)
{
assert(pSL != NULL);
pSL->size = 0; //将顺序表的有效元素个数清空就完成初始化
}
void SeqListDestroy(SeqList *pSL)
{
assert(pSL != NULL);
pSL->size = 0; //将顺序表的有效元素个数清空就完成销毁
}
头插:
void SeqListPushBack(SeqList *pSL,DataType data)
{
assert(pSL != NULL);
assert(pSL->size < MAX_SIZE); //保证有效元素的个数不超过这个数组的大小
//将已有数据往后搬移一格
//这里给出了三种循环的写法:
//1 以要搬移的数来作为循环的指示
#if 0
int pos;
for(pos = pSL->size - 1;pos >= 0;pos--){
pSL->array[pos + 1] = pSL->array[pos];
}
#endif
#if 0 //2 已要搬移到的位置来做循环的指示
int space;
for(space = pSL->size;space > 0;space--){
pSL->array[space] = pSL->array[space - 1];
}
#endif
#if 3 //3 已要循环的次数来作为循环的指示
int i;
for(i = 0;i < pSL->size;i++){
pSL->array[pSL->size - i] = pSL->array[pSL->size - 1 - i];
}
#endif
pSL->array[0] = data;
pSL->size++;
}
尾插:
void SeqListPushBack(SeqList *pSL,DataType data)
{
assert(pSL != NULL);
assert(pSL->size < MAX_SIZE); //保证有效元素的个数不超过数组的大小
pSL->array[pSL->size] = data; //只需将数据添加道有效元素的末尾就完成了尾插
pSL->size++;
}
根据下标插入:
void SeqListInsert(SeqList *pSL,int pos,DataType data)
{
assert(pSL != NULL);
assert(pSL->size < MAX_SIZE); //保证有效元素的个数不超过数组大小
assert(pos >= 0 && pos <= pSL->size) //保证要插入的位置在有效元素的范围中
//把[pos,size)数据往后搬移一格
int space;
for(space = pSL->size;space > pos;space--){ //遍历size,找到pos
pSL->array[space] = pSL->array[space - 1];
}
pSL->array[pos] = data;
pSL->size++
}
尾删:
void SeqListPopBack(SeqList *pSL)
{
assert(pSL != NULL);
assert(pSL->size > 0); //保证有效元素的个数不为0
pSL->size--;
}
头删:
void SeqListPopFront(SeqList *pSL)
{
assert(pSL != NULL);
assert(pSL->size > 0);
//把[1,pSL->size)的数据往前搬移一格
int pos;
for(pos = 1;pos < pSL->size;pos++){
pSL->array[pos - 1] = pSL->array[pos];
}
pSL->size--;
}
根据下标删除:
void SeqListErase(SeqList *pSL,int pos)
{
assert(pSL != NULL);
assert(pSL->size > 0);
assert(pos >= 0 && pos < pSL->size); //保证要删除的数据的下标在有效元素中并且不是最后一个
#if 0
//以要搬运的位置下标作为循环的指示
int space; // 要搬运到的下标位置
for(space = pos;space < pSL->size - 1;space++){
pSL->array[space] = pSL->array[space + 1];
}
#endif
#if 1
//以要搬运的数据下标作为循环的指示
int p; // 要搬运的数据下标
for(p = pos + 1;p < pSL->size;p++){
pSL->array[p - 1] = pSL->array[p];
}
#endif
pSL->size--;
}
根据数据删除,只删除遇到的第一个:
void SeqListRemove(SeqList *pSL,DataType data)
{
int pos = SeqListFind(pSL,data);
if(pos != -1){
//如果找到了
SeqListErase(pSL,pos);
}
}
根据数据删除,删除遇到的所有的:
void SeqListRemoveAll(SeqList *pSL,DataType data)
{
int i,j;
//定义两个变量i,j,让i去遍历整个有效元素的size,在循环中,若array[i]不是要删除的元素,就用另一个变量j保存
for(i = 0,j = 0;i < pSL->size;i++){
if(pSL->array[i] != data){
pSL->array[j] = pSL->array[i];
j++;
}
}
pSL->size = j;
}
根据下标更新:
void SeqListUpdate(SeqList *pSL,int pos,DataType data)
{
assert(pSL != NULL);
assert(pos >= 0 && pos < pSL->size);
pSL->array[pos] = data;
}
查询:返回遇到的第一个下标,若没找到,返回 -1
void SeqListFind(SeqList *pSL,DataType data)
{
assert(pSL != NULL);
int i;
for(i = 0;i < pSL->size;i++){ //定义一个变量遍历有效元素的size
if(pSL->array[i] == data){ //若找到了,返回该下标
return i;
}
}
//没找到
return -1;
}
到这里,静态顺序表的所有基本操作都已介绍完
下一篇,我们介绍另外一种顺序表:动态顺序表