在数据结构的开端,存在一个最简单但是局限性很大的一个数据结构,叫做顺序表
顺序表的书写还是分为SeqList.c,SeqList.h,test.c文件进行书写
先表明顺序表作为数据结构的一种缺陷:由于顺序表的实现大多都用的是数组进行实现,所以他的数据只能进行连续存放在一片内存中
SeqList.h文件
先书写我们所需要的接口函数
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct SeqList
{
int* a;//数组
int size;//顺序表中存储了多少个元素
int capacity;//顺序表中的最大容量
}SL;
void SeqListPrint(SL* ps);//打印整个顺序表
void SeqListInit(SL* ps);//顺序表的初始化
void SeqListDestroy(SL* ps);//顺序表的销毁
void SeqListCheck(SL* ps);//检查顺序表的存储是否足够
void SeqListPushBack(SL* ps,int x);//尾插顺序表
void SeqListPopBack(SL* ps);//尾删顺序表
void SeqListPushFront(SL* ps, int x);//头插顺序表
void SeqListPopFront(SL* ps);//头删顺序表
int SeqListFind(SL* ps, int x);//查找顺序表中的元素,并且返回其下标
void SeqListInsert(SL* ps, int pos, int x);//将元素x插入到pos位置
void SeqListErase(SL* ps, int x);//消除为x的元素
这里看起来顺序表的函数接口十分多,但是由于顺序表的一个结构特征是一个数组,所以大部分的接口采用一个遍历的思想
SeqList.c文件
下面来实现这些接口函数
SeqListInit函数
void SeqListInit(SL* ps)
{
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
由于这里只是对一个顺序表进行初始化,还没有对顺序表进行创造存储空间,所以只需要把size和capacity全部赋值为0即可
SeqListCheck函数
void SeqListCheck(SL* ps)
{
if (ps->capacity == ps->size)
{
int new = 0;
if (ps->capacity == 0)
{
new = 4;
}
else
{
new = ps->capacity * 2;
}
int* tmp = (int*)realloc(ps->a, new * sizeof(int));
if (tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = new;
}
}
注意这个地方判断顺序表是否被装满的条件:顺序表中的容量和已经存放的元素的数量是否相等
同时需要注意realloc的用法
SeqListPushBack函数
这个函数是在顺序表的尾部插入元素
void SeqListPushBack(SL* ps, int x)
{
SeqListCheck(ps);
ps->a[ps->size] = x;
ps->size++;
}
这个尾插函数只需要注意在插入之前先判断顺序表是否需要扩容
SeqListPopBack函数
这个函数是在顺序表的尾部删除元素
void SeqListPopBack(SL* ps)
{
ps->size--;
}
这个接口函数看起来很简单,但是需要对结构体和数组的关系需要有一定的认识
我们只需要将结构体中的size(顺序表存储元素个数)进行减少一个,那么就相当于无法再访问到顺序表的最后一个元素,也就等同于是删除了顺序表的最后一个元素
SeqListPushFront函数
这个函数是在顺序表的头部插入一个元素
void SeqListPushFront(SL* ps, int x)
{
SeqListCheck(ps);
int end = ps->size - 1;
while (end >= 0)
{
end--;
ps->a[end + 1] = ps->a[end];
}
ps->a[0] = x;
ps->size++;
}
这个顺序表的头插需要对顺序表中的数据进行一个移位的处理,先标记最后一个元素的下标end,再将顺序表中的所有元素往后面挪一位
SeqListPopFront函数
void SeqListPopFront(SL* ps)
{
int begin = 1;
while (begin < ps->size)
{
begin++;
ps->a[begin - 1] = ps->a[begin];
}
ps->size--;
}
还是利用一个移位的原理,将第一个元素进行覆盖
SeqListErase函数
void SeqListErase(SL* ps, int x)
{
int i = 0;
int j = 0;
for (i = 0;i < ps->size;i++)
{
if (ps->a[i] == x)
{
for (j = i;j < ps->size;i++)
{
ps->a[j] = ps->a[j + 1];
}
ps->size--;
}
}
}
先对链表中的每个元素做一个遍历,当找到元素的值和我们需要寻找的x的值相同时,记录他的下标为i
然后将下标为i后面的元素全部往前挪一个,这样就可以达到一个消除一个元素的结果
文章介绍了顺序表这一基础数据结构,它使用数组实现,讨论了其存储缺陷和接口函数,包括初始化、检查存储、插入、删除等操作。顺序表在满时需要扩容,通过realloc实现。
653





