目录
悟已往之不谏,知来者犹可追
创作不易,宝子们!如果这篇文章对你们有帮助的话,别忘了给个免费的赞哟~
顺序表是用一段物理地址连续的存储单元以此存储数据的线性结构,一般情况下用数组存储。在数组上完成数据的增删查改~
1. 静态顺序表:用指定长度数组存储元素~
2. 动态顺序表:用动态开辟的数组存储~
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空 间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间 大小,所以下面我们实现动态顺序表。
我们创建一个Test.h里面包含了所有的接口函数声明和各种头文件的声明~
这样我们一个一个实现,正所谓天下难事必做于细~
#define _CRT_SECURE_NO_WARNINGS #pragma once//避免头文件的多次包含 #include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int SLDataType;//便于类型的改动 //定义一个动态顺序表的结构体变量 typedef struct SeqList { SLDataType* arr; size_t num;//记录有效数据的个数 size_t capacity;//该顺序表的容量大小 }SL;//将该结构体类型重命名为SL //加入增删查改接口 //1. 顺序表初始化 void SeqListInit(SL* p); //2. 检查顺序表容量是否已满 void CheckSeqList(SL* p); //3. 顺序表的尾插 void SeqListPushBack(SL* p, SLDataType x); //4. 顺序表的尾删 void SeqListPopBack(SL* p); //5. 顺序表的头插 void SeqListPushFront(SL* p, SLDataType x); //6. 顺序表的头删 void SeqListPopFront(SL* p); //7. 顺序表在pos位置插入 void SeqListInsert(SL* p, size_t pos,SLDataType x); //8. 顺序表在pos位置删除 void SeqListErase(SL* p, size_t pos); //9. 顺序表的查找 int SeqListFind(SL* p,SLDataType x);//如果该数字存在则返回该数字的下标,否则返回-1 //10 顺序表的销毁 void SeqListDestory(SL* p); //11. 顺序表的打印 void SeqListPrint(SL* p);
我们将所有函数的实现放在SeqList.c文件中~
- //1. 顺序表初始化
- void SeqListInit(SL* p)
- {
- assert(p);//判断指针的有效性
- p->arr = NULL;
- p->capacity = 0;
- p->num = 0;
- }
注意我们这里一定要传址调用~
注释写的很详细了,这里就不做过多的解释~
- //2. 检查顺序表容量是否已满
- void CheckSeqList(SL* p)
- {
- assert(p);//判断指针的有效性
- if (p->num == p->capacity)
- {
- size_t newcapacity=p->capacity == 0 ? p->capacity = 4 : p->capacity * 2;
- //如果原来没有空间,就给上4,有的话就扩大为原来的两倍
- SLDataType* ptr = (SLDataType*)realloc(p->arr, newcapacity * sizeof(SLDataType));//动态扩容
- if (ptr == NULL)
- {
- perror("realloc fail;");
- return;
- }
- //也可以用assert断言一下
- p->arr = ptr;//开辟成功将地址传给arr
- p->capacity = newcapacity;//更新容量
- }
- }
- //3. 顺序表的尾插
- void SeqListPushBack(SL* p, SLDataType x)
- {
- assert(p);//判断指针的有效性
- CheckSeqList(p);//尾插前先判断有没有容量或容量够不够
- p->arr[p->num] = x;//尾部插入数据
- p->num++;//有效数加一
- }
- //4. 顺序表的尾删
- void SeqListPopBack(SL* p)
- {
- assert(p);//判断指针的有效性
- assert(p->num > 0);//断言存在有效数据
- p->num--;//尾删一个数据
- }
- //5. 顺序表的头插
- void SeqListPushFront(SL* p, SLDataType x)
- {
- assert(p);//判断指针的有效性
- CheckSeqList(p);//先判断容量是否满了
- size_t end = p->num;
- while (end)
- {
- p->arr[end] = p->arr[end - 1];//整体向后移动
- end--;
- }
- p->arr[0] = x;//头插
- p->num++;//有效数据加一
- }
- //6. 顺序表的头删
- void SeqListPopFront(SL* p)
- {
- assert(p);//判断指针的有效性
- assert(p->num > 0);//有数据才删除
- size_t begin = 1;
- while (begin<p->num)
- {
- p->arr[begin - 1] = p->arr[begin];//整体向前移动
- begin++;
- }
- p->num--;// 有效数据减一
-
- }
整体往前挪,把头覆盖~
- //7. 顺序表在pos位置插入
- void SeqListInsert(SL* p, size_t pos, SLDataType x)
- {
- assert(p);//判断指针的有效性
- assert(pos >= 0 && pos < p->num);//pos必须小于num并且大于等于0
- CheckSeqList(p);//判断容量是否满了
- for (int i = p->num; i >pos-1 ; i--)
- {
- p->arr[i] = p->arr[i - 1];//将pos后面的元素往后挪
- }
- p->arr[pos - 1] = x;//在pos位置加入数据
- p->num++;//有效个数加一
- }
- //8. 顺序表在pos位置删除
- void SeqListErase(SL* p, size_t pos)
- {
- assert(p);//判断指针的有效性
- assert(pos>=0&&pos<p->num );//pos必须小于num并且大于等于0
- assert(p->num > 0);//有数据才能删除
- for (int i = pos; i <p->num; i++)
- {
- p->arr[i-1] = p->arr[i];//将pos后面的元素往后挪
- }
- p->num--;//有效个数减一
- }
遍历数组查找~
- //9. 顺序表的查找
- int SeqListFind(SL* p, SLDataType x)//如果该数字存在则返回该数字的下标,否则返回-1
- {
- assert(p);//断言
- for (int i = 0; i < p->num; i++)
- {
- if (p->arr[i] == x)
- {
- return i;//查到返回下标
- }
- }
- return -1;//没有查到
- }
- //10 顺序表的销毁
- void SeqListDestory(SL* p)
- {
- assert(p);//判断指针的有效性
- free(p->arr );//释放动态内存开辟的空间
- p->arr = NULL;
- p->capacity = 0;//容量置为0
- p->num = 0;//有效个数置为0
- }
- //11. 顺序表的打印
- void SeqListPrint(SL* p)
- {
- assert(p);//判断指针的有效性
- if (p->num == 0)
- {
- printf("顺序表为空!\n");
- return;
- }
- for (int i = 0; i < p->num; i++)
- {
- printf("%d ", p->arr[i]);//打印数据
- }
- printf("\n");
- }
我创建了一个Test.c来测试各个部分的功能~
- #define _CRT_SECURE_NO_WARNINGS
- #include"Test.h"
-
- void TestSeqList()
- {
- SL s1;
- SeqListInit(&s1);//初始化
- SeqListPushBack(&s1, 1);//尾插一个1;
- SeqListPushBack(&s1, 2);//尾插一个2;
- SeqListPushBack(&s1, 3);//尾插一个3;
- SeqListPushBack(&s1, 4);//尾插一个4;
- SeqListPushBack(&s1, 5);//尾插一个5;
- SeqListInsert(&s1, 3, 9);//在第三个位置插入9
- SeqListErase(&s1, 3);//删除第三个位置
- int ret=SeqListFind(&s1, 3);
- if (ret != -1)
- printf("你要查找的数据的下标为:%d\n", ret);
- else
- printf("抱歉,你要查找的数据没有找到!\n");
- //SeqListPopBack(&s1);//尾删一个数据
- //SeqListPushFront(&s1,30);//头插一个数据
- //SeqListPopFront(&s1);//头删一个数据
- SeqListPrint(&s1);//打印数据
- }
-
- int main()
- {
- //测试顺序表
- TestSeqList();
- return 0;
- }
好了,这期的分享到这里就结束了~
如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~
如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~
我们下期不见不散~~