顺序表
数据结构其实都是为了方便在内存中管理数据而设计的数据的存储结构。
🐸一、顺序表介绍
-
顺序表实际上就是数组,每个元素都是连续存储的,物理地址也是连续的,可以用
[]
来访问具体的某个元素。 -
在使用过程中怎么知道顺序表中有多少元素了呢?当然不会选择用全局变量来记录了。
我们其实是把他们封装成一个结构体。
静态顺序表
#define N 7 //最大容量
//用int来代表实际使用过程中顺序表元素的类型
typedef int SLDataType;
typedef Struct SeqList
{
SLDataType array[N];
int size;//存放的元素个数
} SeqList;
- 上例显示了一个顺序表的基本结构,但是如果使用过程中存放的
SLDataType
元素大于7时,显然会出现错误。当然你可以把N定义的足够大,但我们也有更好的解决方案,在顺序表的结构体里新一个变量表示容积,用于判断是否需要扩容。
动态顺序表
typedef int SLDataType;
typedef Struct SeqList
{
SLDataType* a;
int size;//存放的元素个数
int capacity;//容量大小
} SeqList;
🐹二、常见功能即实现
基于对上例动态顺序表。
🐗1. 初始化顺序表
即给SeqList
中每个成员赋值。
void SeqListInit(SeqList* ps)
{
assert(ps);
ps->size = 0;//开始存放0个元素
ps->capacity = 10;//大小设为10
//开辟10个SLDateType的连续空间
ps->a = (SLDateType*)malloc(sizeof(SLDateType) * ps->capacity);
if (ps->a == NULL)//申请失败
{
perror("SeqListInit");
}
}
🐰2. 判断是否需要扩容
因为只有当有空间的时候才能进行添加元素
void SeqListIncrease(SeqList* ps)
{
assert(ps);//当ps==NULL(0)时即为假,报错
if (ps->size == ps->capacity)//当存满了
{
//申请增加10个SeqList空间
SeqList* temp = (SeqList*)realloc(ps, (ps->capacity + 10));
if (temp == NULL)//申请失败
{
perror("SeqListIncrease");
exit(-1);
}
ps = temp;//得到申请的空间
ps->capacity += 10;//容量增10
}
}
🐻3. 打印顺序表
一个for,遍历printf。
void SeqListPrint(SeqList* ps)
{
assert(ps);//当ps==NULL(0)时即为假,报错
//输出size个元素
for (int i = 0; i < ps->size; i++)
{
printf("%d ", *(ps->a + i));
}
printf("\n");
}
🐻❄️4. 头插
即在第一个位置插入一个元素,实现从头添加
void SeqListPushFront(SeqList* ps, SLDateType x)
{
assert(ps);//当ps==NULL(0)时即为假,报错
SeqListIncrease(ps);//判断是否需要扩容
//将size个元素都向后移动一位
for (int i = ps->size; i > 0; i--)
{
*(ps->a + i) = *(ps->a + i - 1);
}
(ps->a)[0] = x;//在第一个位置添加
ps->size++;//个数加1
}
🐨5.尾插
即在后面添加新元素
void SeqListPushBack(SeqList* ps, SLDateType x)
{
assert(ps);//当ps==NULL(0)时即为假,报错
SeqListIncrease(ps);//判断是否需要扩容
*(ps->a + ps->size) = x;//在第size个元素添加
ps->size++;//个数加1
}
🐼6.头删
即删除第一个元素
void SeqListPopFront(SeqList* ps)
{
assert(ps);//当ps==NULL(0)时即为假,报错
//将第2个到第size个元素都向前移动一位,将第一个覆盖掉
for (int i = 0; i < ps->size-1; i++)
{
*(ps->a + i) = *(ps->a + i + 1);
}
ps->size--;//个数减1
}
🦊7.尾删
即删除最后一个元素
void SeqListPopBack(SeqList* ps)
{
assert(ps);//当ps==NULL(0)时即为假,报错
ps->size--;//个数减1
}
🦝8.查找
找到某个SLDataType元素的下标
int SeqListFind(SeqList* ps, SLDateType x)
{
//遍历比较size个元素,有无该x元素
for (int i = 0; i < ps->size; ++i)
{
if (*(ps->a + i) == x)//存在
{
return i;//返回下标
}
}
return -1;//不存在
}
🐮9. 插入
在某个元素的位置,插入一个新元素
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
assert(ps);//当ps==NULL(0)时即为假,报错
//当pos不在[0,ps->size]范围就报错
assert(pos >= 0 && pos <= ps->size);
SeqListIncrease(ps);//判断是否需要扩容
int end = ps->size - 1;//最后一个元素的下标
//将下标为pos到size的元素都向后移动一位
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
--end;
}
ps->a[pos] = x;//在下标为pos的位置添加x
ps->size++;//个数加1
}
🐷10.删除
删除某个元素
void SeqListErase(SeqList* ps, int pos)
{
assert(ps);//当ps==NULL(0)时即为假,报错
//当pos不在[0,ps->size)范围就报错
assert(pos >= 0 && pos < ps->size);
//将pos后的每个元素都向前移动一位
for (int i = pos; i < ps->size-1; i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;//个数减1
}
🦁三、总结
顺序表实现也比较简单,使用也很方便。推荐大家自己动手写一写,希望这篇文章对你有帮助。🦀🦀