1.顺序表的定义
数据结构在内存中的表示通常有两种形式,一种是顺序存储,另一种是链式存储。线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表的数据元素,我们把这种存储形式存储的线性表称为顺序表。
特点:
顺序表的逻辑结构和物理结构是一致的。
顺序表中任意一个数据元素都可以随机存取,所以顺序表是一种随机存取的存储结构。
顺序表的结构定义:
typedef int SLDateType; //定义数据类型,方便后续更改数据类型
typedef struct
{
SLDateType *fp; //定义一个类型指针,
int data; //记录当前数据下标
int size; //记录容量大小;
}SeqList; //重命名为SeqList;
2.顺序表的常用操作实现
2.1顺序表的初始化:
创建顺序表的结构后,结构体里的data与size还有DataType*指针都是随机值,需要手动进行初始化,便于使用,如果不初始化,容易导致bug,或者编译错误。
void SeqListInit(SeqList* ps)
{
ps->a = NULL; //将指针更改为NULL
ps->capacity = ps->size = 0; //将值改为0
}
2.2顺序表的销毁:
退出顺序表后,要将之前mallo开辟的空间给销毁掉, 避免内存泄漏。
void SeqListDestroy(SeqList* ps)
{
assert(ps); //判空一下ps指针
if (ps->a != NULL)
{
free(ps->a); //free掉开辟的空间
}
ps->capacity = ps->size = 0; //将记录的值也置零
}
2.3 判断空间大小以及创建:
使用顺序表存入数据的时候,我们需要先判断检查一下顺序表里的空间容量,当空间容量不足时,无法执行存储数据操作。我们需要先进行空间扩容,然后再把数据存入顺序表中,所以我把这个操作用一个函数封装起来,便于存数据时判断使用。
void SLCheckCapacity(SeqList* ps)
{
assert(ps); //判断ps的指针
if (ps->size == ps->data) //当size与data的值相等时,可以知道当前容量已满,需 { //要进行空间扩容;
int tmp = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDateType* cur = (SLDateType*)realloc(ps->a,sizeof(SLDateType)*tmp);
if (cur == NULL) //防止realloc失败
{
perror("SLCheckCapacity( ): error......"); //当失败时打印信息并返回
return;
}
ps->a = cur;
ps->capacity = tmp;
}
}
2.4顺序表的尾插操作:
void SeqListPushBack(SeqList* ps, SLDateType x)
{
assert(ps);
SLCheckCapacity(ps); //判断空间容量函数接口
ps->a[ps->size] = x; //插入数据,size记录的是下标,使用下标操作直接插入数据
ps->size++; //插入数据后,记得要把size下标+1;
}
2.5 顺序表的头插操作:
void SeqListPushFront(SeqList* ps, SLDateType x)
{
assert(ps);
//判断空间
SLCheckCapacity(ps); //判断空间容量函数接口
for (int a = ps->size; a > 0; a--) //在数据前面插入数据时,需要挪动前面的数据
{ //这里使用循环,将所有数据往后挪一个空间
ps->a[a] = ps->a[a-1];
}
ps->a[0] = x; //将数据x插入在头部位置
ps->size++;
}
2.6 顺序表的头删操作:
void SeqListPopFront(SeqList* ps)
{
assert(ps);
if (ps->size <= 0) //先判断一下该空间有没有数据。
{
printf("已没有数据可删.\n");
return;
}
for (int a=0;a<ps->size-1;a++) //再循环将后面的数据都往前挪一个位置
{
ps->a[a] = ps->a[a + 1];
}
ps->size--; //覆盖完后记得把下标-1
}
2.7 顺序表的尾删操作:
//尾删
void SeqListPopBack(SeqList* ps)
{
assert(ps);
if (ps->size <= 0)
{
printf("已没有数据可删.\n");
return;
}
ps->size--; //删除最后一个数据的话,只需要将下标size-1即可,因为后面再进行插入
} //操作的话,会自动把最后一个数据给覆盖掉。
2.8顺序表的查找:
int SeqListFind(SeqList* ps, SLDateType x)
{
assert(ps);
for (int a = 0; a < ps->size; a++) //顺序表查找的话,需要遍历一遍数据
{
if (ps->a[a] == x)
{
return a; //这里返回数据在顺序表中的下标,
} //有了下标,就可以进行更改或者删除等操作
}
return -1; //如果找不到该数据的下标,即返回-1,便于判断该数据是否存在
}
总结:
顺序表结构简单便于随机访问表中任意的数据元素;缺点是插入和删除操作需要移动大量的数据元素,特别是当顺序表的而数据元素含有复杂信息是,移动工作量大、程序执行效率低。另外,顺序表的存储空间是连续且预先分配,若顺序表的长度变化较大时,难以预估顺序表的长度,可能会造成空间的浪费,也可能会导致数据溢出。
以上内容为本人的学习笔记。