对顺序表的理解
用线性结构来组织元素的方式称为线性数据结构,元素在一段连续空间上按顺序存储,每个元素都有唯一的前驱和后缀。数组和顺序表都是经典的线性数据结构。顺序表采用数组存储元素,也在数组上完成对顺序表操作。
动态顺序表实现
这里给将数据类型重定义为Datatype类型,如果以后要存其他类型的元素只需要把修改int就够了。
typedef int Datatype;
typedef struct Seqlist {
Datatype* array;//指向动态开辟的顺序表的空间
int size;//有效元素的个数
int capacity;//顺序表的总容量
}Seqlist;
初始化方法
初始化一个顺序表,首先开辟一段空间,用malloc,之前动态内存中提到使用malloc要检测空间是否开辟成功,顺序表当前的总容量就是开辟空间的大小,但是不是字节个数,是能存储的有效元素的个数。
当前没有有效元素,size置为0。
void SeqlistInit(Seqlist* ps, int initcap){
//申请空间,
//初始化,将顺序表遍历一遍,然后给上初始化的值就行了
assert(ps);
ps->array = (Datatype*)malloc(initcap * sizeof(Datatype));//使用malloc要判断是否申请成功
//如果ps->array空间开辟失败 触发assert
if (ps->array == NULL) {
assert(0);
}
ps->capacity = initcap;
ps->size = 0;
}
打印顺序表
直接遍历一遍,将size个有效元素打印就行了
void Seqlistprint(Seqlist* ps) {
assert(ps);
int i = 0;
for (i = 0; i < ps->size; i++) {
printf("%d ", ps->array[i]);
}
printf("\n");
}
尾插操作
假设空间足够,顺序表是按数组方式存储的,size个有效元素的数组尾插就是数组下标为size的位置。
找到后直接将data赋进去。
void SeqlistPushback(Seqlist* ps, Datatype Data) {
assert(ps);
ps->array[ps->size] = Data;
ps->size++;
}
任意位置插入操作
顺序表是按顺序存储的,如果4个有效元素,却往下标为8的地方插入数据是访问不到的。所以插入位置pos要小于size 。过程首先将pos到size的元素向后搬移一位,然后将要插入的元素赋给空出来的pos位置。其实所谓搬移也不是pos位置被空出来了。在实现过程中,搬移元素用的是赋值操作,顺序是从后往前,一直将前面的元素覆盖后面的元素,比如 0 1 2 3 4 从2的位置向后搬移,按照这个过程搬移后的数组是 0 1 2 2 3 4,下标位pos的元素依旧在,只是让要插入的数据去覆盖它。这也能理解为什么要从后往前来搬。
void SeqlistInsert(Seqlist* ps, int pos, Datatype Data) {
assert(ps);
if(pos <= ps->size){
int i = 0;
for (i = ps->size; i > pos; i--) {
ps->array[i] = ps->array[i-1];
}
ps->array[pos] = Data;
}
ps->size++;
}
任意位置的删除
实现了插入过程,删除就直接让pos到size的元素先前搬移一位,pos位置的元素就直接被覆盖掉了。
void SeqlistErase(Seqlist* ps, int pos) {
assert(ps);
int i = 0;
for (i = pos; i < ps->size; i++) {
ps->array[i] = ps->array[i + 1];
}
ps->size--;
}
查找元素
遍历顺序表,逐个比较要查找的元素,相等返回所在下标,不相等返回个-1吧。
int SeqlistSeqlistFind(Seqlist* ps, Datatype Data) {
assert(ps);
for (int i = 0; i < ps->size; i++) {
if (Data == ps->array[i]) {
return i;
}
}
return -1;
}
扩容
实现的是动态顺序表,可以根据需要扩容,扩容直接让原来容量扩大到capacity。先判断capacity的合法性,如果传入的比本来的总容量就小,那就不用扩容。扩容操作用动态中的realloc实现,将array空间,扩大到capacity,realloc和malloc一样,使用后要检测是否开辟成功
void SeqlistReserve(Seqlist* ps, int capacity) {
if (capacity <= ps->capacity) {
return;
}
ps->array = (Datatype*)realloc(ps->array, capacity * sizeof(Datatype));
assert(ps->array);
ps->capacity = capacity;
}