当前位置:   article > 正文

数据结构——动态顺序表

数据结构——动态顺序表

数据结构的动态顺序表有以下几个操作:创建,销毁,初始化,增删查改和打印以及内存空间不够时的扩容

本文的宏定义

#define SeqTypeData int

1.动态顺序表的创建

  1. typedef struct SeqListInit{
  2. //动态顺序表的创建
  3. SeqTypeData* a;
  4. int size;//实际有效空间
  5. int capacity;//申请空间大小
  6. }SL;

2.动态顺序表的销毁

  1. void SeqListDestroy(SL* ps) {//顺序表销毁
  2. free(ps->a);
  3. ps->a = NULL;
  4. ps->capacity = ps->size = 0;
  5. };

值得注意的是,ps->a要赋值NULL,避免野指针的出现。

3.动态顺序表的初始化

  1. void SeqListInit(SL* ps){//顺序表初始化
  2. ps->a = NULL;
  3. ps->capacity = ps->size = 0;
  4. };

4.动态顺序表的增加

插入时都要判断空间是否足够,是否需要扩容,以及ps->size要加一。

(1)头插

  1. void SeqListPushFront(SL* ps, SeqTypeData x) {//顺序表头插
  2. SeqListCheckCapacity(ps);//判断是否需要扩容
  3. //挪动数据
  4. ps->size++;
  5. for (int i = 0; i < ps->size; i++) {
  6. ps->a[ps->size - i] = ps->a[ps->size - i - 1];
  7. }
  8. ps->a[0] = x;
  9. }

头插也就是把数据都向后挪一位,再给第一位赋值。

(2)尾插

  1. void SeqListPushBack(SL* ps, SeqTypeData x) {//顺序表尾插
  2. SeqListCheckCapacity(ps);//判断是否需要扩容
  3. ps->a[ps->size++] = x;
  4. }

(3)任意位置插入

  1. void SeqListInsert(SL* ps, int adr, SeqTypeData x)//adr为逻辑地址,等于数组下标加一
  2. {
  3. if (adr > (ps->size + 1) || adr < 1)
  4. {
  5. printf("adr invalid\n");
  6. return;
  7. }
  8. SeqListCheckCapacity(ps);//判断是否需要扩容
  9. int end = ps->size ;
  10. while (end >= adr-1)
  11. {
  12. ps->a[end + 1] = ps->a[end];
  13. --end;
  14. }
  15. ps->a[adr-1] = x;
  16. ps->size++;
  17. }

任意位置插入要记得判断插入位置的合法性,再将插入位置的数据向后移一位,再在插入位置赋值即可。

5.动态顺序表的删除

进行删除操作时,要判断表是否已经是空表,此时不可再删。删除成功时,ps->size减一。

(1)头删

  1. void SeqListPopFront(SL* ps) {//顺序表头删
  2. if (ps->size == 0)
  3. {
  4. printf("顺序表为空,不可再删\n");
  5. }
  6. else
  7. {
  8. for (int i = 0; i < ps->size; i++) {
  9. ps->a[i] = ps->a[i+1];
  10. }
  11. ps->size--;
  12. }
  13. }

(2)尾删

  1. void SeqListPopBack(SL* ps) {//顺序表尾删
  2. if (ps->size--);
  3. else
  4. {
  5. printf("顺序表为空,不可再删\n");
  6. }
  7. }

(3)任意位置删除

  1. void SeqListErase(SL* ps, int adr) {
  2. if (ps->size == 0)
  3. {
  4. printf("顺序表为空,不可再删\n");
  5. }
  6. if (adr > (ps->size + 1))
  7. {
  8. printf("删除位置错误\n");
  9. }
  10. for (int i = adr; i < ps->size; i++) {
  11. ps->a[i-1] = ps->a[i];
  12. }
  13. ps->size--;
  14. }

任意位置的删除也要检验删除位置的合法性。

6.动态顺序表的任意位置的修改

  1. void SeqListCheck(SL* ps, int adr, SeqTypeData x) {//adr为逻辑地址,等于数组下标加一
  2. if(adr>(ps->size+1))
  3. printf("修改位置错误\n");
  4. else
  5. ps->a[adr - 1] = x;
  6. }

任意位置的修改也要检验删除位置的合法性。

7.顺序表的打印

  1. void SeqListPrint(SL ps) {//顺序表打印
  2. for (int i = 0; i < ps.size; i++)
  3. {
  4. printf("%d ", ps.a[i]);
  5. }
  6. }

8.动态顺序表的扩容

  1. void SeqListCheckCapacity(SL* ps) {//顺序表检查是否需要扩容
  2. if (ps->size == ps->capacity) {
  3. SeqTypeData newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
  4. SeqTypeData* tem = (SeqTypeData*)realloc(ps->a, newcapacity * sizeof(SeqTypeData));
  5. if (tem == NULL) {
  6. printf("realloc fail\n");
  7. exit(-1);
  8. }
  9. ps->a = tem;
  10. ps->capacity = newcapacity;
  11. }
  12. }

9.全部代码

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include "SeqList.h"
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <assert.h>
  6. void SeqListInit(SL* ps){//顺序表初始化
  7. ps->a = NULL;
  8. ps->capacity = ps->size = 0;
  9. };
  10. void SeqListDestroy(SL* ps) {//顺序表销毁
  11. free(ps->a);
  12. ps->a = NULL;
  13. ps->capacity = ps->size = 0;
  14. };
  15. void SeqListPrint(SL ps) {//顺序表打印
  16. for (int i = 0; i < ps.size; i++)
  17. {
  18. printf("%d ", ps.a[i]);
  19. }
  20. if (ps.size == 0)
  21. printf("顺序表为空");
  22. printf("\n");
  23. }
  24. //int SeqListCapacity(SL* ps) {//
  25. // return ps->capacity;
  26. //}
  27. void SeqListPushBack(SL* ps, SeqTypeData x) {//顺序表尾插
  28. SeqListCheckCapacity(ps);
  29. ps->a[ps->size++] = x;
  30. }
  31. void SeqListPushFront(SL* ps, SeqTypeData x) {//顺序表头插
  32. SeqListCheckCapacity(ps);
  33. //挪动数据
  34. ps->size++;
  35. for (int i = 0; i < ps->size; i++) {
  36. ps->a[ps->size - i] = ps->a[ps->size - i - 1];
  37. }
  38. ps->a[0] = x;
  39. }
  40. void SeqListCheckCapacity(SL* ps) {//顺序表检查是否需要扩容
  41. if (ps->size == ps->capacity) {
  42. SeqTypeData newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
  43. SeqTypeData* tem = (SeqTypeData*)realloc(ps->a, newcapacity * sizeof(SeqTypeData));
  44. if (tem == NULL) {
  45. printf("realloc fail\n");
  46. exit(-1);
  47. }
  48. ps->a = tem;
  49. ps->capacity = newcapacity;
  50. }
  51. }
  52. void SeqListPopBack(SL* ps) {//顺序表尾删
  53. if (ps->size--);
  54. else
  55. {
  56. printf("顺序表为空,不可再删\n");
  57. }
  58. }
  59. void SeqListPopFront(SL* ps) {//顺序表头删
  60. if (ps->size == 0)
  61. {
  62. printf("顺序表为空,不可再删\n");
  63. }
  64. else
  65. {
  66. for (int i = 0; i < ps->size; i++) {
  67. ps->a[i] = ps->a[i+1];
  68. }
  69. ps->size--;
  70. }
  71. }
  72. void SeqListFind(SL ps, SeqTypeData x) {//顺序表查找
  73. /*int cnt;*/
  74. for (int i = 0; i < ps.size; i++) {
  75. if (ps.a[i] == x) {
  76. printf("%d", i + 1);//返回逻辑下标
  77. /*cnt++;*/
  78. }
  79. }
  80. /*if (cnt == 0)
  81. printf("没有这个数字");*/
  82. }
  83. void SeqListInsert(SL* ps, int adr, SeqTypeData x)//adr为逻辑地址,等于数组下标加一
  84. {
  85. if (adr > (ps->size + 1) || adr < 1)
  86. {
  87. printf("adr invalid\n");
  88. return;
  89. }
  90. SeqListCheckCapacity(ps);
  91. int end = ps->size ;
  92. while (end >= adr-1)
  93. {
  94. ps->a[end + 1] = ps->a[end];
  95. --end;
  96. }
  97. ps->a[adr-1] = x;
  98. ps->size++;
  99. }
  100. void SeqListErase(SL* ps, int adr) {//adr为逻辑地址,等于数组下标加一
  101. if (ps->size == 0)
  102. {
  103. printf("顺序表为空,不可再删\n");
  104. }
  105. if (adr > (ps->size + 1))
  106. {
  107. printf("删除位置错误\n");
  108. }
  109. for (int i = adr; i < ps->size; i++) {
  110. ps->a[i-1] = ps->a[i];
  111. }
  112. ps->size--;
  113. }
  114. void SeqListCheck(SL* ps, int adr, SeqTypeData x) {
  115. if(adr>(ps->size+1))
  116. printf("修改位置错误\n");
  117. else
  118. ps->a[adr - 1] = x;
  119. }
  120. void menu()
  121. {
  122. printf("请选择\n");
  123. printf("********1.头插 2.尾插********\n");
  124. printf("********3.头删 4.尾删********\n");
  125. printf("********5.随插 6.随删********\n");
  126. printf("********7.查找 8.打印********\n");
  127. printf("********9.修改 0.退出********\n");
  128. printf("请选择\n");
  129. }
  130. int main()
  131. {
  132. int input;
  133. SL ps;
  134. SeqTypeData x;
  135. int adr;
  136. SeqListInit(&ps);
  137. do {
  138. menu();
  139. scanf("%d", &input);
  140. switch (input)
  141. {
  142. case 1:
  143. printf("请输入头插数字\n");
  144. scanf("%d", &x);
  145. SeqListPushFront(&ps, x);
  146. break;
  147. case 2:
  148. printf("请输入尾插数字\n");
  149. scanf("%d", &x);
  150. SeqListPushBack(&ps, x);
  151. break;
  152. case 3:
  153. SeqListPopFront(&ps);
  154. break;
  155. case 4:
  156. SeqListPopBack(&ps);
  157. break;
  158. case 5:
  159. printf("请输入插入位置和数字\n");
  160. scanf("%d%d", &adr, &x);
  161. SeqListInsert(&ps, adr, x);
  162. break;
  163. case 6:
  164. printf("请输入删除位置\n");
  165. scanf("%d", &adr);
  166. SeqListErase(&ps, adr);
  167. break;
  168. case 7:
  169. printf("请输入查找数字\n");
  170. scanf("%d", &x);
  171. SeqListFind(ps, x);
  172. break;
  173. case 8:
  174. SeqListPrint(ps);
  175. break;
  176. case 9:
  177. printf("请输入修改位置和数字\n");
  178. scanf("%d%d", &adr, &x);
  179. SeqListCheck(&ps, adr, x);
  180. break;
  181. case 0:
  182. printf("正在退出中");
  183. break;
  184. }
  185. } while (input);
  186. return 0;
  187. }

10.效果展示

由于图片大小问题,只展示了部分功能。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/250375
推荐阅读
相关标签
  

闽ICP备14008679号