• 【数据结构初阶】二、 线性表里的顺序表


    =========================================================================

    相关代码gitee自取

    C语言学习日记: 加油努力 (gitee.com)

     =========================================================================

    接上期

    【数据结构初阶】一. 复杂度讲解_高高的胖子的博客-CSDN博客

     =========================================================================

                          

    1 . 线性表

                   

    线性表linear list)是n个具有相同特性的数据元素的有限序列

    线性表是一种在实际中广泛使用的数据结构

    常见线性表顺序表链表队列字符串...

    顺序表示例:

                  

                  

    线性表逻辑上线性结构,也就说是连续的一条直线

    但是在物理结构上并不一定是连续的

    线性表物理上存储时,通常以数组链式结构形式存储

    链表示例:

             

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                 

    2 . 顺序表

    顺序表概念及结构:

                   

    顺序表一段物理地址连续的存储单元依次存储数据元素线性结构

    一般情况下采用数组存储

    数组上完成数据的增删查改

    顺序表一般可以分为 静态顺序表动态顺序表

                   

                   

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

                    

    因为静态顺序表使用定长数组存储元素

    对空间的运用不够灵活,可能造成空间浪费或不够的问题
    所以在实际情况下静态顺序表并不常用不够实用

    示例:

                        

                        

    动态顺序表:使用动态开辟的数组存储元素

                 

    静态顺序表适用于确定知道需要存多少数据的场景

    静态顺序表定长数组导致N定大了空间开多了浪费开少了不够用

    所以现实中基本都是使用动态顺序表根据需要动态地分配空间大小

    示例:

             

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                 

    3 .接口实现(实现动态顺序表):

    (详细解释在注释,代码分文件放最后)

                    

    数据结构可以管理数据

    通过 增删改查 等操作就可以实现管理数据

                  

    现在有了动态顺序表后

    就可以对其进行增删改查等操作实现动态顺序表

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLInit函数 -- 顺序表初始化

                          

                          

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLDestroy函数 -- 顺序表销毁

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLPrint函数 -- 测试函数

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLPushBack函数 -- 将值插入顺序表尾部(尾插)

    尾插函数SLPushBack测试:

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    上面尾插需要考虑空间不够进行扩容

    后面的头插同样也需要考虑

    所以可以在顺序表实现文件设置一个内部函数SLCheckCapacity,

    在需要的时候直接调用该函数进行扩容操作

    ↓↓↓↓↓

                     

    SLCheckCapacity内部函数 -- 进行扩容操作

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLPopBack函数 -- 将值从顺序表尾部删除(尾删)

    尾删函数SLPopBack测试:

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLPushFront函数 -- 将值插入顺序表头部(头插)

    头插函数SLPushFront测试:

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLPopFront函数 -- 将值从顺序表头部删除(头删)

    头删函数SLPopFront测试:

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLInsert函数 -- 在指定位置(pos)插入想要的值(x)

    指定添加函数SLInsert测试:

                 

    这里写了指定位置插入SLInsert函数

    可以想到其实 头插 尾插 也是可以用 SLInsert函数 实现的

    所以可以在头插和尾插函数中复用 SLInsert函数减少代码量

    ↓↓↓↓↓

                      

    复用SLInsert函数 -- 改写头插函数SLPushFront

                         

    复用SLInsert函数 -- 改写尾插函数SLPushBack

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    上面SLInsert函数涉及了插入位置pos下标

    有时在增删改查操作时,需要知道有效元素中某个元素的下标再进行操作,

    所以我们可以定义一个函数SLFind查找该元素的下标

    ↓↓↓↓↓

                     

    SLFind函数 -- 查找x这个值在顺序表中的下标是多少

    查找函数SLFind测试:

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLErase函数 -- 删除指定位置(pos)的值

    删除指定位置函数SLErase测试:

                       

    完成指定删除SLErase函数

    头删 尾删 函数中也可以进行复用 SLErase函数 减少代码量

    ↓↓↓↓↓

                      

    用SLErase函数 -- 改写头删函数SLPopFront

                         

    用SLErase函数 -- 改写尾删函数SLPopBack

                          

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SLModify函数 -- 把某个位置(pos)的值修改为某值(x)

    修改函数SLModify测试:

              

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                 

    4 . 对应代码

    SeqList.h -- 顺序表头文件

    1. #pragma once
    2. 定义一个静态顺序表:使用定长数组存储元素
    3. 因为静态顺序表使用定长数组存储元素,对空间的运用不够灵活
    4. 所以在实际情况下,静态顺序表并不常用(不够实用)
    5. //
    6. //#define N 1000 //“表”的大小的值
    7. //typedef int SLDataType; //定义顺序表中存储的类型,这里是int类型
    8. //
    9. //struct SeqList
    10. //{
    11. // SLDataType a[N]; //定义表的大小
    12. // int size; //记录表中存储了多少个有效数据
    13. //};
    14. //将需要的头文件都包含在 SeqList.h 头文件中
    15. #include
    16. #include
    17. #include
    18. //定义一个动态顺序表:使用动态开辟的数组存储元素
    19. typedef int SLDataType; //定义顺序表中存储的类型,这里是int类型
    20. typedef struct SeqList
    21. {
    22. //定义一个顺序表类型的指针,指向动态开辟的数组
    23. SLDataType* a;
    24. int size; //记录表中存储了多少个有效数据
    25. int capactity; //容量空间的大小
    26. }SL;
    27. //数据结构 --> 管理数据 --> 增删查改
    28. //顺序表初始化 -- 头文件中声明
    29. void SLInit(SL* ps);
    30. //顺序表销毁 -- 头文件中声明
    31. //内存是动态开辟地,不销毁的话可能会导致内存泄漏)
    32. void SLDestroy(SL* ps);
    33. //写一个测试函数(声明),方便检查各步骤有没有问题:
    34. void SLPrint(SL* ps);
    35. //尾插(声明) -- 将值插入顺序表尾部:
    36. void SLPushBack(SL* ps, SLDataType x);
    37. //尾删(声明) -- 将值从顺序表尾部删除:
    38. void SLPopBack(SL* ps);
    39. //头插(声明) -- 将值插入顺序表头部:
    40. void SLPushFront(SL* ps, SLDataType x);
    41. //头删(声明) -- 将值从顺序表头部删除:
    42. void SLPopFront(SL* ps);
    43. //在指定位置(pos)插入想要的值(x)
    44. void SLInsert(SL* ps, int pos, SLDataType x);
    45. //查找x这个值在顺序表中的下标是多少:
    46. int SLFind(SL* ps, SLDataType x); //返回找到的下标
    47. //删除指定位置(pos)的值:
    48. void SLErase(SL* ps, int pos);
    49. //把某个位置(pos)的值修改为某值(x)
    50. void SLModify(SL* ps, int pos, SLDataType x);

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    SeqList.c -- 顺序表实现文件

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. //包含我们写的 SeqList.h 头文件
    3. #include "SeqList.h"
    4. //顺序表初始化 -- 实现
    5. void SLInit(SL* ps)
    6. {
    7. //assert断言,防止接收空指针:
    8. assert(ps);
    9. //初始化顺序表类型指针
    10. //初始化时要先开辟一些动态空间:
    11. //开辟的空间为顺序表类型,大小为4个顺序表类型的大小
    12. ps->a = (SLDataType*)malloc(sizeof(SLDataType)*4);
    13. //顺序表作为一个独立的程序,之后可能会应用于其他程序,
    14. //所以要对开辟的动态空间进行检查:
    15. if (ps->a == NULL)
    16. {
    17. //可能开辟的空间过大 或 前面开辟太多空间不够再开辟
    18. perror("malloc failed"); //打印错误
    19. //让程序以异常的形式结束程序
    20. //和 return 不同,return后主函数还会继续进行
    21. exit(-1);
    22. }
    23. //将顺序表中的有效数据初始化为0:
    24. ps->size = 0;
    25. //将已动态开辟的容量空间初始化为4:
    26. ps->capactity = 4;
    27. }
    28. //顺序表销毁 -- 实现
    29. //内存是动态开辟地,不销毁的话可能会导致内存泄漏)
    30. void SLDestroy(SL* ps)
    31. {
    32. //assert断言,防止接收空指针:
    33. assert(ps);
    34. //释放前面开辟的动态空间:
    35. free(ps->a);
    36. //将释放的指针置为空指针:
    37. ps->a = NULL;
    38. //将已开辟的动态空间置为0,顺序表有效数据也置为0
    39. ps->capactity = ps->size = 0;
    40. }
    41. //写一个测试函数(实现),方便检查各步骤有没有问题:
    42. void SLPrint(SL* ps)
    43. {
    44. //assert断言,防止接收空指针:
    45. assert(ps);
    46. //打印动态顺序表现有的有效数据:
    47. for (int i = 0; i < ps->size; i++)
    48. {
    49. printf("%d ", ps->a[i]);
    50. }
    51. //打印完当前动态顺序表有效数据后进行换行:
    52. printf("\n");
    53. }
    54. //在顺序表实现文件中设置一个内部函数SLCheckCapacity,
    55. //在需要的时候直接调用该函数进行扩容操作
    56. void SLCheckCapacity(SL* ps)
    57. {
    58. //assert断言,防止接收空指针:
    59. assert(ps);
    60. //判断开辟的空间是否已满,满了再开辟:
    61. if (ps->size == ps->capactity)
    62. //顺序表有效个数 等于 已开辟容量空间
    63. {
    64. //使用 realloc函数 进行扩容,每次扩容2倍:
    65. SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capactity * 2 * (sizeof(SLDataType)));
    66. // realloc 是把空间扩容到第二个参数的大小,而不是直接把空间扩容第二个参数的大小
    67. //同样进行检验:
    68. if (tmp == NULL)
    69. {
    70. //打印错误:
    71. perror("realloc failed");
    72. //出现错误直接终止程序:
    73. exit(-1);
    74. }
    75. //realloc函数,有两种扩容情况:一种是原地扩容,另一种是异地扩容
    76. //原地扩容:扩容时看原空间后的内容有没有分配给别人,如果没有则把原空间后面的空间标记出来进行扩容,返回原空间的地址
    77. //异地扩容:如果扩容时原空间后面的内容已被分配,则另找一个足够原空间扩容后的空间进行存放,
    78. // 原本的数据都搬到这个空间来,原空间会被释放,返回这个新空间的地址。
    79. //所以使用 realloc函数 扩容后,不要对原空间指针进行释放,
    80. //如果realloc执行后是原地扩容返回原空间指针,扩容后后对原空间指针释放就会出问题
    81. //把扩容返回的指针赋给原指针:
    82. ps->a = tmp;
    83. //将已动态开辟的容量空间置为原来的2倍:
    84. ps->capactity *= 2;
    85. }
    86. }
    87. //尾插(实现) -- 将值插入顺序表尾部:
    88. void SLPushBack(SL* ps, SLDataType x)
    89. {
    90. //assert断言,防止接收空指针:
    91. assert(ps);
    92. 调用内部函数进行扩容操作:
    93. //SLCheckCapacity(ps);
    94. 空间容量足够后将要插入尾部的值插入:
    95. //ps->a[ps->size] = x;
    96. 因为下标从0开始,所以size的值会等于现有元素下一位的下标
    97. //ps->size++; //尾部插入元素后,更新顺序表中有效数据个数
    98. //复用SLInsert函数 -- 改写尾插函数SLPushBack
    99. SLInsert(ps, ps->size, x); //在size位置插入就相当于尾插
    100. }
    101. //尾删(实现) -- 将值从顺序表尾部删除:
    102. void SLPopBack(SL* ps)
    103. {
    104. //assert断言,防止接收空指针:
    105. assert(ps);
    106. 检查一下:如果有效数据size等于0,则不能继续删除了
    107. 防止越界,可能一直删除到空间外了导致越界
    108. //
    109. 检查方法一:太“温柔”,返回后不知道自己错了
    110. if (ps->size == 0)
    111. {
    112. return; //直接返回 即可
    113. }
    114. //
    115. 检查方法二:使用断言,错误了会直接报错并给出错误信息
    116. //assert(ps->size > 0); //顺序表中有效数据大于0才进行下面的操作
    117. 直接有效数据size--即可
    118. 尾插是也是用size插入的,所以下次添加时直接就覆盖了原来值
    119. //ps->size--;
    120. 不能局部释放,不能说不要末尾的值就把末尾的这个空间直接释放掉
    121. C++有个规定,malloc一次就要free一次,要free释放的话只能整体释放
    122. 顺序表的物理内存是连续的,释放空间是不能“分期”的
    123. //复用SLErase函数 -- 改写尾删函数SLPopBack
    124. SLErase(ps, ps->size-1); //size-1 就是最末元素下标
    125. }
    126. //头插(实现) -- 将值插入顺序表头部:
    127. void SLPushFront(SL* ps, SLDataType x)
    128. {
    129. //assert断言,防止接收空指针:
    130. assert(ps);
    131. 调用内部函数进行扩容操作:
    132. //SLCheckCapacity(ps);
    133. 将现有有效数据往后移一位,让出头位置:
    134. //int end = ps->size - 1;
    135. size-1 有效个数-1,就相当于当前最后一个元素的下标
    136. //while (end >= 0)
    137. // //使用while循环循环移动各个有效元素,一直移到下标为0的元素
    138. //{
    139. // ps->a[end + 1] = ps->a[end]; //end下标元素 移到 下一位上
    140. // --end; //改变下标
    141. //}
    142. 将要插入头部的元素x插入头部:
    143. //ps->a[0] = x;
    144. 有效个数加一:
    145. //ps->size++;
    146. Capacity在扩容函数SLCheckCapacity中就修改好了
    147. //复用SLInsert函数 -- 改写头插函数SLPushFront
    148. SLInsert(ps, 0, x); //在0位置插入就相当于头插
    149. }
    150. //头删(实现) -- 将值从顺序表头部删除:
    151. void SLPopFront(SL* ps)
    152. {
    153. //assert断言,防止接收空指针:
    154. assert(ps);
    155. 因为要将头部的有效元素删除,
    156. 所以直接把第一个有效元素后面的其他元素往前移一位就行了,
    157. 覆盖掉第一个元素
    158. 先进行断言检查,防止没有元素还进行删除:
    159. //assert(ps->size > 0);
    160. //int begin = 1; //从下标为1的元素开始往前移,把下标为0的元素覆盖
    161. //while (begin < ps->size)
    162. // //只要begin还小于有效元素个数就继续往前移
    163. // //因为是从下标为1的元素开始移动,
    164. // //所以最后就只有下标为0的元素没动
    165. //{
    166. // //把当前begin下标的元素往前挪一位:
    167. // ps->a[begin - 1] = ps->a[begin];
    168. // //当前begin下标元素移动后,begin++继续移动下一位:
    169. // ++begin;
    170. //}
    171. //
    172. 因为第一个元素被覆盖,所以有效元素size--
    173. //ps->size--;
    174. //复用SLErase函数 -- 改写头删函数SLPopFront
    175. SLErase(ps, 0); //头元素下标是0
    176. }
    177. //在指定位置(pos)插入想要的值(x)
    178. void SLInsert(SL* ps, int pos, SLDataType x)
    179. {
    180. //先使用assert检查pos是否合法:
    181. //在pos位置插入一个值后,顺序表还得是连续的
    182. assert(pos >= 0 && pos <= ps->size);
    183. //pos等于0 -- 相等于头插
    184. //pos等于size -- 相等于尾插
    185. //使用SLCheckCapacity进行扩容操作:
    186. SLCheckCapacity(ps);
    187. //定义一个变量end,对应要移动元素的下标
    188. int end = ps->size - 1; //一开始对应最后一个元素的下标
    189. while (end >= pos)
    190. //只要end下标对应的元素还在pos下标元素的右边
    191. //就把“end元素”向右移,移到pos下标无元素
    192. {
    193. //把“end元素”向右移
    194. ps->a[end + 1] = ps->a[end];
    195. //移动下标进行写一个元素的移动
    196. --end;
    197. }
    198. //让出位置后,将接收的x插入pos位置:
    199. ps->a[pos] = x;
    200. //有效元素+1:
    201. ps->size++;
    202. }
    203. //查找x这个值在顺序表中的下标是多少:
    204. int SLFind(SL* ps, SLDataType x) //返回找到的下标
    205. {
    206. //assert断言,防止接收空指针:
    207. assert(ps);
    208. //数据量不大的话直接暴力查找吧:
    209. for (int i = 0; i < ps->size; i++)
    210. //有几个有效元素就循环几次:
    211. {
    212. if (ps->a[i] == x)
    213. //该下标元素等于要找的值x则返回当前下标:
    214. {
    215. return i;
    216. }
    217. }
    218. return -1; //表未找到该元素下标
    219. }
    220. //删除指定位置(pos)的值:
    221. void SLErase(SL* ps, int pos)
    222. {
    223. //同样先使用assert检查pos是否合法:
    224. //这里检查条件pos不能像SLInsert一样等于size
    225. //因为size空了能插入(尾插),但不能删除
    226. assert(pos >= 0 && pos < ps->size);
    227. //指定删除和头删的思路类似,
    228. //只要把pos后面的值往前覆盖,覆盖掉pos的值就好了:
    229. int begin = pos + 1; //从pos+1的位置往前挪
    230. while (begin < ps->size)
    231. //一直移到size为止(不包括size位置)
    232. {
    233. ps->a[begin - 1] = ps->a[begin]; //往前挪
    234. ++begin; //挪完继续挪下一个
    235. }
    236. ps->size--; //覆盖掉pos位置的值后,有效数字减一
    237. }
    238. //把pos位置的值修改为x
    239. void SLModify(SL* ps, int pos, SLDataType x)
    240. {
    241. //同样先使用assert断言检查pos是否合法:
    242. assert(pos >= 0 && pos < ps->size);
    243. //进行修改:
    244. ps->a[pos] = x;
    245. }

                            

    --------------------------------------------------------------------------------------------------------------------------

                      

                          

    test.c -- 测试函数

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. //包含我们写的 SeqList.h 头文件
    3. #include "SeqList.h"
    4. //分组测试,测试不同的函数--SLPushBack 和 SLPopBack 函数
    5. void TestSeqList1()
    6. {
    7. SL sl; //创建顺序表类型变量
    8. //使用 SLInit函数 初始化顺序表类型变量
    9. //注意传递的是变量的地址,防止形参改变实参不改变
    10. SLInit(&sl);
    11. //使用尾插函数SLPushBack:
    12. SLPushBack(&sl, 1);
    13. SLPushBack(&sl, 2);
    14. SLPushBack(&sl, 3);
    15. SLPushBack(&sl, 4);
    16. //此时再调用会进行扩容:
    17. SLPushBack(&sl, 5);
    18. SLPushBack(&sl, 6);
    19. //调用测试函数SPrint查看是否插入成功:
    20. SLPrint(&sl);
    21. //测试尾删函数SLPopBack:
    22. SLPopBack(&sl);
    23. SLPopBack(&sl);
    24. //调用测试函数SPrint查看是否“删除”成功:
    25. SLPrint(&sl);
    26. //测试完后使用SLDestroy函数销毁顺序表:
    27. SLDestroy(&sl);
    28. }
    29. //分组测试,测试不同的函数--SLPushFront函数
    30. void TestSeqList2()
    31. {
    32. SL sl; //创建顺序表类型变量
    33. //使用 SLInit函数 初始化顺序表类型变量
    34. //注意传递的是变量的地址,防止形参改变实参不改变
    35. SLInit(&sl);
    36. //使用尾插函数SLPushBack:
    37. SLPushBack(&sl, 1);
    38. SLPushBack(&sl, 2);
    39. SLPushBack(&sl, 3);
    40. SLPushBack(&sl, 4);
    41. //此时再调用会进行扩容:
    42. SLPushBack(&sl, 5);
    43. SLPushBack(&sl, 6);
    44. //调用测试函数SPrint查看是否插入成功:
    45. SLPrint(&sl);
    46. //测试头插函数SLPushFront:
    47. SLPushFront(&sl, 10);
    48. SLPushFront(&sl, 20);
    49. //调用测试函数SPrint查看是否“删除”成功:
    50. SLPrint(&sl);
    51. //测试完后使用SLDestroy函数销毁顺序表:
    52. SLDestroy(&sl);
    53. }
    54. //分组测试,测试不同的函数--SLPopFront函数
    55. void TestSeqList3()
    56. {
    57. SL sl; //创建顺序表类型变量
    58. //使用 SLInit函数 初始化顺序表类型变量
    59. //注意传递的是变量的地址,防止形参改变实参不改变
    60. SLInit(&sl);
    61. //使用尾插函数SLPushBack:
    62. SLPushBack(&sl, 1);
    63. SLPushBack(&sl, 2);
    64. SLPushBack(&sl, 3);
    65. SLPushBack(&sl, 4);
    66. //此时再调用会进行扩容:
    67. SLPushBack(&sl, 5);
    68. SLPushBack(&sl, 6);
    69. //调用测试函数SPrint查看是否插入成功:
    70. SLPrint(&sl);
    71. //测试头删函数SLPopFront:
    72. SLPopFront(&sl);
    73. SLPopFront(&sl);
    74. //调用测试函数SPrint查看是否“删除”成功:
    75. SLPrint(&sl);
    76. //测试完后使用SLDestroy函数销毁顺序表:
    77. SLDestroy(&sl);
    78. }
    79. //分组测试,测试不同的函数--SLInsert函数
    80. void TestSeqList4()
    81. {
    82. SL sl; //创建顺序表类型变量
    83. //使用 SLInit函数 初始化顺序表类型变量
    84. //注意传递的是变量的地址,防止形参改变实参不改变
    85. SLInit(&sl);
    86. //使用尾插函数SLPushBack:
    87. SLPushBack(&sl, 1);
    88. SLPushBack(&sl, 2);
    89. SLPushBack(&sl, 3);
    90. SLPushBack(&sl, 4);
    91. //此时再调用会进行扩容:
    92. SLPushBack(&sl, 5);
    93. SLPushBack(&sl, 6);
    94. //调用测试函数SPrint查看是否插入成功:
    95. SLPrint(&sl);
    96. //测试指定增加函数SLInsert:
    97. SLInsert(&sl, 2, 100);
    98. //调用测试函数SPrint查看是否“删除”成功:
    99. SLPrint(&sl);
    100. //int x;
    101. //scanf("%d", &x);
    102. //int pos = SLFind(&sl, x);
    103. //if (pos != -1)
    104. //{
    105. // SLInsert(&sl, pos, x * 10);
    106. //}
    107. //SLPrint(&sl);
    108. //测试完后使用SLDestroy函数销毁顺序表:
    109. SLDestroy(&sl);
    110. }
    111. //分组测试,测试不同的函数--SLFind函数
    112. void TestSeqList5()
    113. {
    114. SL sl; //创建顺序表类型变量
    115. //使用 SLInit函数 初始化顺序表类型变量
    116. //注意传递的是变量的地址,防止形参改变实参不改变
    117. SLInit(&sl);
    118. //使用尾插函数SLPushBack:
    119. SLPushBack(&sl, 1);
    120. SLPushBack(&sl, 2);
    121. SLPushBack(&sl, 3);
    122. SLPushBack(&sl, 4);
    123. //此时再调用会进行扩容:
    124. SLPushBack(&sl, 5);
    125. SLPushBack(&sl, 6);
    126. //调用测试函数SPrint查看是否插入成功:
    127. SLPrint(&sl);
    128. //测试指定增加函数SLFind:
    129. int pos = SLFind(&sl, 2);
    130. printf("2在元素中是第%d个元素", pos+1);
    131. //测试完后使用SLDestroy函数销毁顺序表:
    132. SLDestroy(&sl);
    133. }
    134. //分组测试,测试不同的函数--SLErase函数
    135. void TestSeqList6()
    136. {
    137. SL sl; //创建顺序表类型变量
    138. //使用 SLInit函数 初始化顺序表类型变量
    139. //注意传递的是变量的地址,防止形参改变实参不改变
    140. SLInit(&sl);
    141. //使用尾插函数SLPushBack:
    142. SLPushBack(&sl, 1);
    143. SLPushBack(&sl, 2);
    144. SLPushBack(&sl, 3);
    145. SLPushBack(&sl, 4);
    146. //此时再调用会进行扩容:
    147. SLPushBack(&sl, 5);
    148. SLPushBack(&sl, 6);
    149. //调用测试函数SPrint查看是否插入成功:
    150. SLPrint(&sl);
    151. int x;
    152. scanf("%d", &x);
    153. //配合SLFind函数,找到顺序表中某个值的下标
    154. int pos = SLFind(&sl, x);
    155. //再使用SLErase函数通过下标删除该值
    156. if (pos != -1)
    157. {
    158. SLErase(&sl, pos);
    159. }
    160. SLPrint(&sl);
    161. //测试完后使用SLDestroy函数销毁顺序表:
    162. SLDestroy(&sl);
    163. }
    164. //分组测试,测试不同的函数--SLModify函数
    165. void TestSeqList7()
    166. {
    167. SL sl; //创建顺序表类型变量
    168. //使用 SLInit函数 初始化顺序表类型变量
    169. //注意传递的是变量的地址,防止形参改变实参不改变
    170. SLInit(&sl);
    171. //使用尾插函数SLPushBack:
    172. SLPushBack(&sl, 1);
    173. SLPushBack(&sl, 2);
    174. SLPushBack(&sl, 3);
    175. SLPushBack(&sl, 4);
    176. //此时再调用会进行扩容:
    177. SLPushBack(&sl, 5);
    178. SLPushBack(&sl, 6);
    179. //调用测试函数SPrint查看是否插入成功:
    180. SLPrint(&sl);
    181. //测试指定增加函数SLInsert:
    182. SLModify(&sl, 2, 100);
    183. //调用测试函数SPrint查看是否“删除”成功:
    184. SLPrint(&sl);
    185. //测试完后使用SLDestroy函数销毁顺序表:
    186. SLDestroy(&sl);
    187. }
    188. //菜单:
    189. void menu()
    190. {
    191. printf("********************************\n");
    192. printf("1、尾插 2、头插\n");
    193. printf("3、头删 4、尾删\n");
    194. printf("7、打印 -1、退出\n");
    195. printf("********************************\n");
    196. }
    197. int main()
    198. {
    199. //先创建一个顺序表:
    200. SL sl;
    201. //再对其进行初始化:
    202. SLInit(&sl);
    203. //创建一个变量接收菜单选项:
    204. int option = 0;
    205. do
    206. {
    207. //使用菜单:
    208. menu();
    209. //打印提示信息:
    210. printf("请选择想要进行的操作的序号:>");
    211. //接收序号:
    212. scanf("%d", &option);
    213. printf("\n");
    214. if (option == 1)
    215. {
    216. printf("请依次输入你要插入的数据个数:>");
    217. int n = 0; //接收数据个数
    218. scanf("%d", &n); //接收数据个数
    219. printf("\n");
    220. printf("请依次输入你要插入的数据\n");
    221. //知道数据个数后,直接使用for循环循环接收数据
    222. int x = 0;
    223. for (int i = 0; i < n; i++)
    224. {
    225. scanf("%d", &x);
    226. SLPushBack(&sl, x);
    227. }
    228. }
    229. else if (option == 7)
    230. {
    231. SLPrint(&sl);
    232. }
    233. } while (option != -1);
    234. //最后销毁顺序表:
    235. SLDestroy(&sl);
    236. //TestSeqList1();
    237. //TestSeqList2();
    238. //TestSeqList3();
    239. //TestSeqList4();
    240. //TestSeqList5();
    241. //TestSeqList6();
    242. //TestSeqList7();
    243. return 0;
    244. }
  • 相关阅读:
    在kubernetes里使用seccomp限制容器的系统调用
    kubernetes之crontab
    Redis缓存穿透、缓存雪崩和缓存击穿
    金融行业软文怎么写,如何让金融软文在发布上有好效果?
    王道计网:数据链路层
    javaIO流07:处理流BufferedReader和BufferedWriter,Buffer拷贝
    Java校园跑腿小程序校园代买帮忙外卖源码社区外卖源码
    机器学习——推荐系统和强化学习
    SpringMVC的请求处理流程及核心组件
    java架构知识点-中间件(学习笔记)
  • 原文地址:https://blog.csdn.net/weixin_63176266/article/details/132699782