• 【数据结构】顺序表 详解(初始化、增、删、查、改)


    🐱作者:傻响
    🐱专栏:《数据结构与算法 - 顺序表》
    🔥格言:你只管努力,剩下的交给时间!

    1.顺序表🤩

    1.1概念及结构🤢

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

            1. 静态顺序表:使用定长数组存储元素。

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

            动态的顺序表和静态的静态表理论是一直的,唯一的区别在于静态的顺序表是判断是否存储区容量已满,而静态的动态的顺序表是判断如果存储区容量满了就进行扩容。

    1.2 接口实现:🤢

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

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. // 动态顺序表。
    6. typedef int SLDataType;
    7. typedef struct SeqList
    8. {
    9. SLDataType* data; // 存储数据和内容数量。
    10. size_t size; // 存储数据的个数。
    11. int capacity; // 存储空间的大小。
    12. }SeqList;
    13. // 增、删、查、改接口。
    14. // 顺序表初始化函数声明。
    15. void SLInit(SeqList* pSL);
    16. // 顺序表销毁函数声明。
    17. void SLDestory(SeqList* pSL);
    18. // 顺序表尾插头插函数声明。
    19. void SLPushBack(SeqList* pSL, SLDataType data);
    20. void SLPushFront(SeqList* pSL, SLDataType data);
    21. // 顺序表查找函数声明。
    22. int SLFind(SeqList* pSL, SLDataType data);
    23. // 顺序表出入函数声明。
    24. void SLInset(SeqList* pSL, size_t pos, SLDataType data);
    25. // 顺序表尾删头删函数声明。
    26. void SLPopBack(SeqList* pSL);
    27. void SLPopFront(SeqList* pSL);
    28. // 顺组表删除函数声明。
    29. void SLErase(SeqList* pSL, size_t pos);
    30. // 顺组表修改函数声明。
    31. void SLModifi(SeqList* pSL, size_t pos, SLDataType data);
    32. // 顺序表打印。
    33. void SLPrint(const SeqList* pSL);

    2.顺序表代码讲解🤩

    🤢2.1顺序表初始化

    1. // 顺序表初始化实现。
    2. void SLInit(SL* pSL)
    3. {
    4. // 断言 - - 检测指针变量是否为空。
    5. assert(pSL);
    6. pSL->data = NULL;
    7. pSL->capacity = pSL->size = 0;
    8. }

    🤢3.2顺序表销毁

    1. // 顺序表销毁实现。
    2. void SLDestory(SL* pSL)
    3. {
    4. // 断言 - - 检测指针变量是否为空。
    5. assert(pSL);
    6. if (pSL->data != NULL) //如果顺序表不等于空,执行。
    7. {
    8. free(pSL->data);
    9. pSL->data = NULL;
    10. pSL->capacity = pSL->size = 0;
    11. }
    12. }

     🤢2.3顺序表尾插

    1. void SLPushBack(SeqList* pSL, SLDataType incomeData)
    2. {
    3. // 断言保护指针形参。
    4. assert(pSL);
    5. // 判断容量是否可以继续存储数据。
    6. SLCheakCapacity(pSL);
    7. // 扩容完成/或者容量够用。
    8. pSL->data[pSL->size] = incomeData;
    9. pSL->size++;
    10. }

     🤢3.4顺序表头插

             

    1. // 顺序表头插。
    2. void SLPushFront(SL* pSL, SLDataType data)
    3. {
    4. // 断言 - - 检测指针变量是否为空。
    5. assert(pSL);
    6. // 检查容量。
    7. SLCheckCapacity(pSL);
    8. // 移动数据
    9. int end = pSL->size - 1;
    10. while (end >= 0)
    11. {
    12. pSL->data[end + 1] = pSL->data[end];
    13. end--;
    14. }
    15. // 头部存入数据
    16. pSL->data[0] = data;
    17. pSL->size++;
    18. }

            我们在这里做了一下检测容量的调整,因检测数据被重复调用很多次,所以封装了一个函数SLCheckCapacity(),让其他的函数可以进行多次调用。

     

    🤢3.5顺序表尾删除

            尾删除的话是比较简单的。

    1. // 顺序表尾删。
    2. void SLPopBack(SL* pSL)
    3. {
    4. // 断言 - - 检测指针变量是否为空。
    5. assert(pSL);
    6. // 检测还是否有数据。
    7. if (pSL->size == 0)
    8. return 0;
    9. // 进行理论上的删除
    10. pSL->size--;
    11. }

    🤢3.6顺序表头删除

    1. // 顺序表头删实现。
    2. void SLPopFront(SL* pSL)
    3. {
    4. // 断言 - - 检测指针变量是否为空。
    5. assert(pSL);
    6. // 检测还是否有数据。
    7. if (pSL->size == 0)
    8. return;
    9. //从后向前移动数据。
    10. for (int i = 0; i < pSL->size-1; i++)
    11. {
    12. pSL->data[i] = pSL->data[i + 1];
    13. }
    14. --pSL->size;
    15. }

    🤢3.6顺序表查找

    1. // 顺序表查找函数实现。
    2. int SLFind(SeqList* pSL, SLDataType data)
    3. {
    4. // 断言 - - 检测指针变量是否为空。
    5. assert(pSL);
    6. // 查找数据.
    7. for (int i = 0; i < pSL->size; i++)
    8. {
    9. if (pSL->data[i] == data)
    10. return i;
    11. }
    12. // 如果没有找到的话返回-1.
    13. return -1;
    14. }

    🤢3.7顺序表插入pos位置数据

    1. // 顺序表出入函数声明声明
    2. void SLInset(SeqList* pSL, size_t pos, SLDataType data)
    3. {
    4. // 断言 - - 检测指针变量是否为空。
    5. assert(pSL);
    6. // 检测要插入的位置是否越界。
    7. assert(pos <= (size_t)pSL->size);
    8. // 容量检查。
    9. SLCheckCapacity(pSL);
    10. // 移动数据。
    11. size_t end = pSL->size;
    12. while (end > pos)
    13. {
    14. pSL->data[end] = pSL->data[end - 1];
    15. end--;
    16. }
    17. pSL->data[pos] = data;
    18. pSL->size++;
    19. }

    🤢3.8顺序表删除pos位置数据

    1. // 顺组表删除函数实现。
    2. void SLErase(SeqList* pSL, size_t pos)
    3. {
    4. // 断言 - - 检测指针变量是否为空。
    5. assert(pSL);
    6. // 检测要插入的位置是否越界。
    7. assert(pos < pSL->size);
    8. // 删除数据(数据后往前移动到pos处)
    9. for (size_t begin = pos; begin < pSL->size - 1; begin++)
    10. {
    11. pSL->data[begin] = pSL->data[begin + 1];
    12. }
    13. --pSL->size;
    14. }

    当然在这里我们就可以把之前的头删和尾删进行复用SLErase()这个函数。

            修改代码如下:

    1. // 顺序表尾删函数实现。
    2. void SLPopBack(SeqList* pSL)
    3. {
    4. 断言 - - 检测指针变量是否为空。
    5. //assert(pSL);
    6. 检测还是否有数据。
    7. //if (pSL->size == 0)
    8. // return;
    9. 进行理论上的删除
    10. //pSL->size--;
    11. SLErase(pSL, pSL->size - 1);
    12. }
    13. // 顺序表头删函数实现。
    14. void SLPopFront(SeqList* pSL)
    15. {
    16. 断言 - - 检测指针变量是否为空。
    17. //assert(pSL);
    18. 检测还是否有数据。
    19. //if (pSL->size == 0)
    20. // return;
    21. 从后向前移动数据。
    22. //for (size_t i = 0; i < pSL->size - 1; i++)
    23. //{
    24. // pSL->data[i] = pSL->data[i + 1];
    25. //}
    26. //--pSL->size;
    27. SLErase(pSL, 0);
    28. }

    🤢3.9顺序表修改pos位置数据

            这个修改的代码就简单实现

    1. // 顺组表修改函数实现。
    2. void SLModifi(SeqList* pSL, size_t pos, SLDataType data)
    3. {
    4. // 断言 - - 检测指针变量是否为空。
    5. assert(pSL);
    6. // 检测要插入的位置是否越界。
    7. assert(pos < pSL->size);
    8. // 修改数据
    9. pSL->data[pos] = data;
    10. }

    😍到此位置我们简单入门级别的顺序表就全部完成了。

  • 相关阅读:
    IOday5
    Unity 安卓(Android)端AVProVideo插件播放不了视频,屏幕一闪一闪的
    java面试100题(应届生必备)
    基于Springboot外卖系统10:公共字段填充功能+ThreadLocal模块改进
    vue3响应式系统
    spring为什么要使用三级缓存来解决循环依赖
    Jetson nano嵌入式平台配置ip记录
    9、Neural Sparse Voxel Fields
    719. 找出第 K 小的数对距离-二分查找
    oracle 迁移PG 博客
  • 原文地址:https://blog.csdn.net/lx473774000/article/details/126303559