一、写在介绍前
顺序表是啥?
1. 顺序表底层就是数组。
2.顺序表是线性表(具有相同特性的数据结构的集合)的一种。
3.顺序表分为静态顺序表和动态顺序表。
处理文件
1.我们用seqlist.h记录顺序表结构,声明顺序表方法
2.我们用seqlist.c实现顺序表的方法
3.我们用test.c测试代码
二、代码运算
我会带着大家实现顺序表的增、删、改、查。
三、代码实现
1.定义顺序表结构
注意定义的时候在seqlist.h里面定义。写一个动态顺序表,可以动态增容,成倍速的增加。
typedef int sltype;
typedef struct seqlist
{
sltype* arr;
int size;
int capacity;
}sl;
这里之所以要使用typedef类型重命名,就是为了在数组类型发生改变时可以只对重定义的类型直接更改就可以了,这样也不会发生代码的任何错误。
2.顺序表初始化
初始化即实现,所以在seqlist.c里面进行。
void slinit(sl* ps) {
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
记得在seqlist.h定义函数。
3.写一个函数申请空间
void slCheckCapacity(sl* ps) {
if (ps->capacity == ps->size) {
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
//使用realloc可以增加容量
sltype* tmp=(sltype*)realloc(ps->arr, newcapacity * sizeof(sltype));//要申请多大空间
if (tmp == NULL) {
perror("realloc");
exit(1);//直接退出,程序不再执行
}
//空间申请成功
ps->arr = tmp;
ps->capacity = newcapacity;
}
}
4.尾部插入删除
尾部插入很简单:就是在数组下标为size的地方进行插入一个数据,而增加了一个数据,数组大小size也会加1。
void slpushback(sl* ps, sltype x) {
assert(ps);//断言一下,避免ps是空指针
slCheckCapacity(ps);//检查空间是否足够
ps->arr[ps->size++] = x;//进行尾部插入
//后置++即先用后加,用过for循环的都知道,和i++一样的道理
}
尾部删除就更简单了:删完数据就少一个,然后检查数组个数是否为空,最后直接减少数组个数就可以了
void slpopback(sl* ps) {
assert(ps);
//顺序表不能为空
assert(ps->size);
//只进行--操作不影响增删查改
--ps->size;
}
5.头部插入删除
头部插入
void slpushfront(sl* ps, sltype x) {
assert(ps);
slCheckCapacity(ps);
//把数组的前面一个赋值到后面一个,把数组的第一个位置留出来
for (int i = ps->size; i > 0; i--) {
ps->arr[i] = ps->arr[i - 1];
}
//在头部插入数据
ps->arr[0] = x;
//插入的数据要算在数组大小里面,所以记得++
ps->size++;
}
头部删除
void slpopfront(sl* ps) {
assert(ps);
assert(ps->size);
int i;
//把后面一个数据赋值到前一个数据
for (i = 0; i < ps->size; i++) {
ps->arr[i] = ps->arr[i + 1];
}
//最后对数组大小进行--以达到头部删除的效果
ps->size--;
}
6.指定位置之前插入
void slinsert(sl* ps, int pos, sltype x) {
assert(ps);
assert(pos >= 0&&pos<=ps->size);
//插入数据,空间够不够
slCheckCapacity(ps);
//让pos及之后的数据整体往后挪
int i;
for (i = ps->size; i > pos; i--) {
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[pos] = x;
ps->size++;
}
7.删除指定位置的数据
void slerase(sl* ps, int pos) {
assert(ps);
//指定位置删除,该位置必须小于size,不能等于size
assert(pos >= 0 && pos < ps->size);
int i;
for (i = pos; i < ps->size-1; i++) {
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
8.顺序表的查找
int slfind(sl* ps, sltype x) {
assert(ps);
int i;
for (i = 0; i < ps->size; i++) {
if (ps->arr[i] == x) {
return i;
}
}
return -1;
}
四、完整demo
-
seqlist.h(函数声明/顺序表结构体)
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int sltype;
typedef struct seqlist
{
sltype* arr;
int size;
int capacity;
}sl;
//typedef struct seqlist sl;
//初始化和销毁
void slinit(sl* ps);
void sldestroy(sl* ps);
void slprint(sl s);
//扩容
void slCheckCapacity(sl* ps);
//尾部插入删除/头部插入删除
void slpushback(sl* ps, sltype x);
void slpopback(sl* ps);
void slpushfront(sl* ps, sltype x);
void slpopfront(sl* ps);
//指定位置之前插入/删除数据
void slinsert(sl* ps, int pos, sltype x);
void slerase(sl* ps, int pos);
//顺序表的查找
int slfind(sl* ps, sltype x);
-
seqlist.c(函数实现)
#include"seqlist.h"
void slinit(sl* ps) {
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
//申请空间
void slCheckCapacity(sl* ps) {
if (ps->capacity == ps->size) {
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
sltype* tmp=(sltype*)realloc(ps->arr, newcapacity * sizeof(sltype));
if (tmp == NULL) {
perror("realloc");
exit(1);//直接退出,程序不再执行
}
ps->arr = tmp;
ps->capacity = newcapacity;
}
}
void sldestroy(sl* ps) {
if (ps->arr) {
free(ps->arr);
}
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
void slprint(sl s) {
int i;
for (i = 0; i < s.size; i++) {
printf("%d ", s.arr[i]);
}
printf("\n");
}
//尾部插入删除
void slpushback(sl* ps, sltype x) {
assert(ps);
slCheckCapacity(ps);
ps->arr[ps->size++] = x;
}
void slpopback(sl* ps) {
assert(ps);
//顺序表不能为空
assert(ps->size);
//只进行--操作不影响增删查改
--ps->size;
}
//头部插入删除
void slpushfront(sl* ps, sltype x) {
assert(ps);
slCheckCapacity(ps);
for (int i = ps->size; i > 0; i--) {
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[0] = x;
ps->size++;
}
void slpopfront(sl* ps) {
assert(ps);
assert(ps->size);
int i;
for (i = 0; i < ps->size; i++) {
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//指定位置之前插入
void slinsert(sl* ps, int pos, sltype x) {
assert(ps);
assert(pos >= 0&&pos<=ps->size);
//插入数据,空间够不够
slCheckCapacity(ps);
//让pos及之后的数据整体往后挪
int i;
for (i = ps->size; i > pos; i--) {
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[pos] = x;
ps->size++;
}
//删除指定位置的数据
void slerase(sl* ps, int pos) {
assert(ps);
assert(pos >= 0 && pos < ps->size);
int i;
for (i = pos; i < ps->size-1; i++) {
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//顺序表的查找
int slfind(sl* ps, sltype x) {
assert(ps);
int i;
for (i = 0; i < ps->size; i++) {
if (ps->arr[i] == x) {
return i;
}
}
return -1;
}
-
text.c(测试代码)
以下代码仅仅为我测试数据所用,可以参考。
#include"seqlist.h"
void text01() {
sl sa;
slinit(&sa);
//增删查改
//尾插
slpushback(&sa, 1);
slpushback(&sa, 2);
slpushback(&sa, 3);
slpushback(&sa, 4);
slprint(sa);
//尾删
slpopback(&sa);
slprint(sa);
//头插
slpushfront(&sa,5);
slprint(sa);
//头删
slpopfront(&sa);
slprint(sa);
//顺序表销毁
sldestroy(&sa);
}
void text02(){
sl s1;
slinit(&s1);
slpushback(&s1, 1);
slpushback(&s1, 2);
slpushback(&s1, 3);
slpushback(&s1, 4);
slprint(s1);
//指定位置插入一个数
slinsert(&s1, 0, 99);
slprint(s1);
sldestroy(&s1);
}
//删除指定位置的数据
void text03() {
sl s1;
slinit(&s1);
slpushback(&s1, 1);
slpushback(&s1, 2);
slpushback(&s1, 3);
slpushback(&s1, 4);
slprint(s1);
slerase(&s1, 3);
slprint(s1);
sldestroy(&s1);
}
//顺序表的查找
void text04() {
sl s1;
slinit(&s1);
slpushback(&s1, 1);
slpushback(&s1, 2);
slpushback(&s1, 3);
slpushback(&s1, 4);
slprint(s1);
int find=slfind(&s1, 4);
if (find > 0) {
printf("找到了,下标为%d", find);
}
else {
printf("没有找到");
}
sldestroy(&s1);
}
int main() {
text01();
text02();
text03();
text04();
return 0;
}
五、小结
本文主要介绍了顺序表的增删查改,希望我的文章可以帮助初学者快速掌握顺序表的具体内容,后续我还会发出顺序表的应用——写一个通讯录,感兴趣的朋友可以点进我的主页查找。