什么是顺序表
用【一段连续的物理空间】存储数据的线性结构。数据必须从第一个位置开始,连续存储.
一般采用数组存储。
顺序表的实现(C语言实现)
定义顺序表的结构体
#define N 100
typedef int SLDataType;//先定顺序表中的数据是整型
//静态顺序表:N小可能存不下数据,N太大空间浪费,不实用
/*struct SeqList
{
SLDataType a[N];//存储顺序表中数据的数组
int size; //当前已有的数据个数
};*/
//动态顺序表
typedef struct SeqList
{
SLDataType* a;//指向动态开辟的空间
int size;//已有的数据个数,顺序表规定:数据必须从第一个位置开始连续存储
int capacity;//当前容量,当已有的数据量比容量大时,要扩容
}SL;
相关函数
顺序表的初始化和销毁
void SLInit(SL* seqlist)//顺序表初始化
{
assert(seqlist);
seqlist->capacity = 4;//初始容量设置
SLDataType* tem = (SLDataType*)malloc(sizeof(SLDataType) * seqlist->capacity);
if (tem == NULL)
{
perror("malloc fail");
exit(-1);
}
seqlist->a = tem;
seqlist->size = 0;
}
void SLDestroy(SL* seqlist)//顺序表的销毁
{
assert(seqlist);
free(seqlist->a);
}
顺序表的增删查改
尾插与尾删
时间复杂度为O(1)
void SLPushBack(SL* seqlist, SLDataType x)//顺序表尾插
{
assert(seqlist);
SLCheckCapacity(seqlist);//用来检查是否需要扩容的函数,后面会实现
seqlist->a[seqlist->size] = x;
seqlist->size++;
}
void SLPopBack(SL* seqlist)//顺序表尾删
{
assert(seqlist && seqlist->size > 0);//数据量必须大于0
seqlist->size--;
}
头插与头删
时间复杂度为O(N)
void SLPushFront(SL* seqlist, SLDataType x)//顺序表头插
{
assert(seqlist);
SLCheckCapacity(seqlist);//用来检查是否需要扩容的函数
//从后往前 向后挪动数据
int end = seqlist->size - 1;//下标从0开始,seqlist->size是最后一个数据的下一个位置
while (end >= 0)
{
seqlist->a[end + 1] = seqlist->a[end];
end--;
}
seqlist->a[0] = x;
seqlist->size++;
}
void SLPopFront(SL* seqlist)//顺序表头删
{
assert(seqlist&&seqlist->size > 0);//数据量必须大于0
//从前往后 向前挪动数据
int begin = 0;
while(begin <seqlist->size - 1)
{
seqlist->a[begin] = seqlist->a[begin+1];
begin++;
}
seqlist->size--;
}
任意位置的插入和删除
void SLInsert(SL* seqlist, int pos, SLDataType x)//顺序表任意位置插入数据
{
assert(seqlist);
assert(pos >= 0 && pos <= seqlist->size);
SLCheckCapacity(seqlist);
//顺序表插入数据是(从后往前) 向后挪数据
int end = seqlist->size - 1;
while (end >= pos)
{
seqlist->a[end + 1] = seqlist->a[end];
end--;
}
seqlist->a[pos] = x;
seqlist->size++;
}
void SLErase(SL* seqlist, int pos)//顺序表删除任意位置的数据
{
assert(seqlist && seqlist->size > 0);
assert(pos >= 0 && pos < seqlist->size);
//顺序表删除数据是(从前往后)向前挪数据
int begin = pos;
while (begin < seqlist->size - 1)
{
seqlist->a[begin] = seqlist->a[begin + 1];
begin++;
}
seqlist->size--;
}
查找与修改
int SLSearch(SL* seqlist, SLDataType x) //顺序表中查找(返回下标)
{
assert(seqlist);
for (int i = 0; i < seqlist->size; i++)
{
if (x == seqlist->a[i])
return i;
}
return -1;//没有找到返回-1
}
void SLModify(SL* seqlist, int pos, SLDataType x)//把pos位置的值修改成x
{
assert(seqlist && pos >= 0 && pos < seqlist->size);
seqlist->a[pos] = x;
}
其它函数
1 插入数据都需要检查容量是否足够
void SLCheckCapacity(SL* seqlist)
{
assert(seqlist);
if (seqlist->capacity == seqlist->size)//如果已有的数据个数=容量并且要继续插入,先扩容
{
int newcapacity = seqlist->capacity * 2;
SLDataType* a = (SLDataType*)realloc(seqlist->a, newcapacity * sizeof(SLDataType));
if (a == NULL)
{
perror("realloc fail");
exit(-1);
}
seqlist->a = a;
seqlist->capacity *= 2;
}
}
2 打印顺序表的数据
void SLPrint(SL* seqlist)//打印顺序表数据
{
assert(seqlist);
for (int i = 0; i < seqlist->size; i++)
{
printf("%d ", seqlist->a[i]);
}
putchar('\n');
}