• 数据结构之顺序表及其实现!


    目录

    ​编辑

    1. 顺序表的概念及结构

    2. 接口的实现

    2.1 顺序表的初始化

    2.2 检查顺序表容量是否已满

    2.3 顺序表的尾插

    ​编辑

    2.4 顺序表的尾删

    2.5 顺序表的头插

    2.6  顺序表的头删

    2.7 顺序表在pos位置插入

    2.8  顺序表在pos位置删除

    2.9 顺序表的查找

    2.10 顺序表的销毁

    2.11 顺序表的打印

     3. 我在实现顺序表时的测试代码

    4. 完结散花


                                                悟已往之不谏,知来者犹可追  

    创作不易,宝子们!如果这篇文章对你们有帮助的话,别忘了给个免费的赞哟~

    1. 顺序表的概念及结构

    顺序表是用一段物理地址连续的存储单元以此存储数据的线性结构,一般情况下用数组存储。在数组上完成数据的增删查改~

    1. 静态顺序表:用指定长度数组存储元素~

    2. 动态顺序表:用动态开辟的数组存储~

    2. 接口的实现

    静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空 间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间 大小,所以下面我们实现动态顺序表。

    我们创建一个Test.h里面包含了所有的接口函数声明和各种头文件的声明~

    这样我们一个一个实现,正所谓天下难事必做于细~

    1. #define _CRT_SECURE_NO_WARNINGS
    2. #pragma once//避免头文件的多次包含
    3. #include<stdio.h>
    4. #include<assert.h>
    5. #include<stdlib.h>
    6. typedef int SLDataType;//便于类型的改动
    7. //定义一个动态顺序表的结构体变量
    8. typedef struct SeqList
    9. {
    10. SLDataType* arr;
    11. size_t num;//记录有效数据的个数
    12. size_t capacity;//该顺序表的容量大小
    13. }SL;//将该结构体类型重命名为SL
    14. //加入增删查改接口
    15. //1. 顺序表初始化
    16. void SeqListInit(SL* p);
    17. //2. 检查顺序表容量是否已满
    18. void CheckSeqList(SL* p);
    19. //3. 顺序表的尾插
    20. void SeqListPushBack(SL* p, SLDataType x);
    21. //4. 顺序表的尾删
    22. void SeqListPopBack(SL* p);
    23. //5. 顺序表的头插
    24. void SeqListPushFront(SL* p, SLDataType x);
    25. //6. 顺序表的头删
    26. void SeqListPopFront(SL* p);
    27. //7. 顺序表在pos位置插入
    28. void SeqListInsert(SL* p, size_t pos,SLDataType x);
    29. //8. 顺序表在pos位置删除
    30. void SeqListErase(SL* p, size_t pos);
    31. //9. 顺序表的查找
    32. int SeqListFind(SL* p,SLDataType x);//如果该数字存在则返回该数字的下标,否则返回-1
    33. //10 顺序表的销毁
    34. void SeqListDestory(SL* p);
    35. //11. 顺序表的打印
    36. void SeqListPrint(SL* p);

    我们将所有函数的实现放在SeqList.c文件中~

    2.1 顺序表的初始化

    1. //1. 顺序表初始化
    2. void SeqListInit(SL* p)
    3. {
    4. assert(p);//判断指针的有效性
    5. p->arr = NULL;
    6. p->capacity = 0;
    7. p->num = 0;
    8. }

     注意我们这里一定要传址调用~

    2.2 检查顺序表容量是否已满

     注释写的很详细了,这里就不做过多的解释~

    1. //2. 检查顺序表容量是否已满
    2. void CheckSeqList(SL* p)
    3. {
    4. assert(p);//判断指针的有效性
    5. if (p->num == p->capacity)
    6. {
    7. size_t newcapacity=p->capacity == 0 ? p->capacity = 4 : p->capacity * 2;
    8. //如果原来没有空间,就给上4,有的话就扩大为原来的两倍
    9. SLDataType* ptr = (SLDataType*)realloc(p->arr, newcapacity * sizeof(SLDataType));//动态扩容
    10. if (ptr == NULL)
    11. {
    12. perror("realloc fail;");
    13. return;
    14. }
    15. //也可以用assert断言一下
    16. p->arr = ptr;//开辟成功将地址传给arr
    17. p->capacity = newcapacity;//更新容量
    18. }
    19. }

    2.3 顺序表的尾插

    1. //3. 顺序表的尾插
    2. void SeqListPushBack(SL* p, SLDataType x)
    3. {
    4. assert(p);//判断指针的有效性
    5. CheckSeqList(p);//尾插前先判断有没有容量或容量够不够
    6. p->arr[p->num] = x;//尾部插入数据
    7. p->num++;//有效数加一
    8. }

    2.4 顺序表的尾删

    1. //4. 顺序表的尾删
    2. void SeqListPopBack(SL* p)
    3. {
    4. assert(p);//判断指针的有效性
    5. assert(p->num > 0);//断言存在有效数据
    6. p->num--;//尾删一个数据
    7. }

     

    2.5 顺序表的头插

    1. //5. 顺序表的头插
    2. void SeqListPushFront(SL* p, SLDataType x)
    3. {
    4. assert(p);//判断指针的有效性
    5. CheckSeqList(p);//先判断容量是否满了
    6. size_t end = p->num;
    7. while (end)
    8. {
    9. p->arr[end] = p->arr[end - 1];//整体向后移动
    10. end--;
    11. }
    12. p->arr[0] = x;//头插
    13. p->num++;//有效数据加一
    14. }

     

    2.6  顺序表的头删

    1. //6. 顺序表的头删
    2. void SeqListPopFront(SL* p)
    3. {
    4. assert(p);//判断指针的有效性
    5. assert(p->num > 0);//有数据才删除
    6. size_t begin = 1;
    7. while (begin<p->num)
    8. {
    9. p->arr[begin - 1] = p->arr[begin];//整体向前移动
    10. begin++;
    11. }
    12. p->num--;// 有效数据减一
    13. }

     整体往前挪,把头覆盖~

    2.7 顺序表在pos位置插入

    1. //7. 顺序表在pos位置插入
    2. void SeqListInsert(SL* p, size_t pos, SLDataType x)
    3. {
    4. assert(p);//判断指针的有效性
    5. assert(pos >= 0 && pos < p->num);//pos必须小于num并且大于等于0
    6. CheckSeqList(p);//判断容量是否满了
    7. for (int i = p->num; i >pos-1 ; i--)
    8. {
    9. p->arr[i] = p->arr[i - 1];//将pos后面的元素往后挪
    10. }
    11. p->arr[pos - 1] = x;//在pos位置加入数据
    12. p->num++;//有效个数加一
    13. }

     

    2.8  顺序表在pos位置删除

    1. //8. 顺序表在pos位置删除
    2. void SeqListErase(SL* p, size_t pos)
    3. {
    4. assert(p);//判断指针的有效性
    5. assert(pos>=0&&pos<p->num );//pos必须小于num并且大于等于0
    6. assert(p->num > 0);//有数据才能删除
    7. for (int i = pos; i <p->num; i++)
    8. {
    9. p->arr[i-1] = p->arr[i];//将pos后面的元素往后挪
    10. }
    11. p->num--;//有效个数减一
    12. }

    2.9 顺序表的查找

    遍历数组查找~

    1. //9. 顺序表的查找
    2. int SeqListFind(SL* p, SLDataType x)//如果该数字存在则返回该数字的下标,否则返回-1
    3. {
    4. assert(p);//断言
    5. for (int i = 0; i < p->num; i++)
    6. {
    7. if (p->arr[i] == x)
    8. {
    9. return i;//查到返回下标
    10. }
    11. }
    12. return -1;//没有查到
    13. }

    2.10 顺序表的销毁

    1. //10 顺序表的销毁
    2. void SeqListDestory(SL* p)
    3. {
    4. assert(p);//判断指针的有效性
    5. free(p->arr );//释放动态内存开辟的空间
    6. p->arr = NULL;
    7. p->capacity = 0;//容量置为0
    8. p->num = 0;//有效个数置为0
    9. }

    2.11 顺序表的打印

    1. //11. 顺序表的打印
    2. void SeqListPrint(SL* p)
    3. {
    4. assert(p);//判断指针的有效性
    5. if (p->num == 0)
    6. {
    7. printf("顺序表为空!\n");
    8. return;
    9. }
    10. for (int i = 0; i < p->num; i++)
    11. {
    12. printf("%d ", p->arr[i]);//打印数据
    13. }
    14. printf("\n");
    15. }

     3. 我在实现顺序表时的测试代码

    我创建了一个Test.c来测试各个部分的功能~

    1. #define _CRT_SECURE_NO_WARNINGS
    2. #include"Test.h"
    3. void TestSeqList()
    4. {
    5. SL s1;
    6. SeqListInit(&s1);//初始化
    7. SeqListPushBack(&s1, 1);//尾插一个1
    8. SeqListPushBack(&s1, 2);//尾插一个2
    9. SeqListPushBack(&s1, 3);//尾插一个3
    10. SeqListPushBack(&s1, 4);//尾插一个4
    11. SeqListPushBack(&s1, 5);//尾插一个5
    12. SeqListInsert(&s1, 3, 9);//在第三个位置插入9
    13. SeqListErase(&s1, 3);//删除第三个位置
    14. int ret=SeqListFind(&s1, 3);
    15. if (ret != -1)
    16. printf("你要查找的数据的下标为:%d\n", ret);
    17. else
    18. printf("抱歉,你要查找的数据没有找到!\n");
    19. //SeqListPopBack(&s1);//尾删一个数据
    20. //SeqListPushFront(&s1,30);//头插一个数据
    21. //SeqListPopFront(&s1);//头删一个数据
    22. SeqListPrint(&s1);//打印数据
    23. }
    24. int main()
    25. {
    26. //测试顺序表
    27. TestSeqList();
    28. return 0;
    29. }

    4. 完结散花

    好了,这期的分享到这里就结束了~

    如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

    如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

    我们下期不见不散~~

  • 相关阅读:
    Day34力扣打卡
    UnrealEngine5 - Niagara粒子系统问题 当发射器不在视口内时,发射物不可见
    Django路由层和视图层
    关于安卓jxl的excel操作(一)
    分享几个可以免费使用GPT的网站
    Docker的四种网络模式
    electron
    线性回归的正则方法:岭回归和Lasso
    程序员不得不知道的 API 接口常识
    超级适合小白!学Java必读书籍,强烈推荐
  • 原文地址:https://blog.csdn.net/2301_80221228/article/details/136517162