飞道的博客

数据结构-顺序表基本操作的实现(含全部代码)

608人阅读  评论(0)

今天起开始编写数据结构中的各种数据结构及其算法的实现。

主要依据严蔚敏版数据结构教材以及王道数据结构考研辅导书。

今天是线性表中的顺序表的实现,主要实现函数如下,读者有需要可以评论,我可以适当加几个。

  • CreateList(SqList &L,int n) 参数:顺序表L,顺序表长度n 功能:创建长度为的顺序表 时间复杂度:O(n)
  • InitList(SqList &L) 参数:顺序表L 功能:初始化 时间复杂度:O(1)
  • InsertList(SqList &L,int i,ElemType e) 参数:顺序表L,位置i,元素e 功能:位置i处插入元素e 时间复杂度:O(n)
  • ListDelete(SqList &L,int i) 参数:顺序表L,位置i 功能:删除位置i处元素 时间复杂度:O(n)
  • LocateElem(SqList L,ElemType e) 参数:顺序表L,元素e 功能:返回第一个等于e的元素的位置 时间复杂度:O(n)
  • Reverse(SqList &L) 参数:顺序表L 倒置函数 将原顺序表直接倒置
  • PrintList(SqList L) 参数:顺序表L 功能:遍历L,并输出
  • SplitSort(SqList &L) 参数:顺序表L 功能:分开奇偶,并分开排序
  • ClearList(SqList &L) 参数:顺序表L 功能:清空顺序表

代码如下:


  
  1. /*
  2. Project: sequence_list(数据结构-顺序表)
  3. Date: 2018/09/12 20191012修改 添加Reverse 20200819修改 添加ClearList
  4. Author: Frank Yu
  5. CreateList(SqList &L,int n) 参数:顺序表L,顺序表长度n 功能:创建长度为的顺序表 时间复杂度:O(n)
  6. InitList(SqList &L) 参数:顺序表L 功能:初始化 时间复杂度:O(1)
  7. InsertList(SqList &L,int i,ElemType e) 参数:顺序表L,位置i,元素e 功能:位置i处插入元素e 时间复杂度:O(n)
  8. ListDelete(SqList &L,int i) 参数:顺序表L,位置i 功能:删除位置i处元素 时间复杂度:O(n)
  9. LocateElem(SqList L,ElemType e) 参数:顺序表L,元素e 功能:返回第一个等于e的元素的位置 时间复杂度:O(n)
  10. Reverse(SqList &L) 参数:顺序表L 倒置函数 将原顺序表直接倒置
  11. PrintList(SqList L) 参数:顺序表L 功能:遍历L,并输出
  12. SplitSort(SqList &L) 参数:顺序表L 功能:分开奇偶,并分开排序
  13. ClearList(SqList &L) 参数:顺序表L 功能:清空顺序表
  14. */
  15. #include<cstdio>
  16. #include<cstdlib>
  17. #include<cstring>
  18. #include<cmath>
  19. #include<algorithm>
  20. #include<iostream>
  21. #define MaxSize 100
  22. #define ElemType int
  23. #define Status int
  24. using namespace std;
  25. //顺序表数据结构
  26. typedef struct
  27. {
  28. ElemType data[MaxSize]; //顺序表元素
  29. int length; //顺序表当前长度
  30. }SqList;
  31. //***************************基本操作函数*******************************//
  32. //初始化顺序表函数,构造一个空的顺序表
  33. Status InitList(SqList &L)
  34. {
  35. memset(L.data, 0, sizeof(L)); //初始化数据为0
  36. L.length = 0; //初始化长度为0
  37. return 0;
  38. }
  39. //创建顺序表函数 初始化前n个数据
  40. bool CreateList(SqList &L, int n)
  41. {
  42. if (n< 0 || n>MaxSize) false; //n非法
  43. for ( int i = 0; i<n; i++)
  44. {
  45. scanf( "%d", &L.data[i]);
  46. L.length++;
  47. }
  48. return true;
  49. }
  50. //插入函数 位置i插入数据 i及之后元素后移 1=<i<=length+1
  51. bool InsertList(SqList &L, int i, ElemType e)
  52. {
  53. if (i< 1 || i>L.length + 1) //判断位置是否有效
  54. {
  55. printf( "位置无效!!!\n");
  56. return false;
  57. }
  58. if (L.length >= MaxSize) //判断存储空间是否已满
  59. {
  60. printf( "当前存储空间已满!!!\n");
  61. return false;
  62. }
  63. for ( int j = L.length; j >= i; j--) //位置i及之后元素后移
  64. {
  65. L.data[j] = L.data[j - 1];
  66. }
  67. L.data[i - 1] = e;
  68. L.length++;
  69. return true;
  70. }
  71. //删除函数 删除位置i的元素 i之后的元素依次前移
  72. bool ListDelete(SqList &L, int i)
  73. {
  74. if (i< 1 || i>L.length)
  75. {
  76. printf( "位置无效!!!\n");
  77. return false;
  78. }
  79. for ( int j = i; j <= L.length - 1; j++) //位置i之后元素依次前移覆盖
  80. {
  81. L.data[j - 1] = L.data[j];
  82. }
  83. L.length--;
  84. return true;
  85. }
  86. //查找函数 按位置从小到大查找第一个值等于e的元素 并返回位置
  87. int LocateElem(SqList L, ElemType e)
  88. {
  89. for ( int i = 0; i<L.length; i++) //从低位置查找
  90. {
  91. if (L.data[i] == e)
  92. return i + 1;
  93. }
  94. return 0;
  95. }
  96. //倒置函数 将原顺序表直接倒置
  97. void Reverse(SqList &L)
  98. {
  99. if (L.length)
  100. for ( int i = 0; i<L.length - 1 - i; i++)
  101. {
  102. int t = L.data[i];
  103. L.data[i] = L.data[L.length - 1 - i];
  104. L.data[L.length - 1 - i] = t;
  105. }
  106. }
  107. //奇偶分开并排序
  108. void SplitSort(SqList &L)
  109. {
  110. int Even = 0;
  111. int Odd = L.length - 1;
  112. int i = 0;
  113. int j = L.length - 1;
  114. bool flag = false;
  115. if (L.length)
  116. for (; i < j; i++, j--)
  117. {
  118. while (L.data[i] % 2 != 0)i++;
  119. while (L.data[j] % 2 == 0)j--;
  120. if (L.data[i] % 2 == 0 && L.data[j] % 2 != 0&&i<j)
  121. {
  122. int temp = L.data[i];
  123. L.data[i] = L.data[j];
  124. L.data[j] = temp;
  125. flag = true;
  126. }
  127. if(!flag) //没有交换
  128. {
  129. Even = L.length - 1; //全奇数
  130. Odd = 0; //全偶数
  131. }
  132. }
  133. if (flag)
  134. {
  135. for( int i= 0;i<L.length;i++)
  136. if (L.data[i] % 2 == 0)
  137. {
  138. Odd = i;
  139. Even = i - 1;
  140. break;
  141. }
  142. }
  143. sort(L.data, L.data + Even + 1);
  144. sort(L.data + Odd, L.data + L.length);
  145. }
  146. //清空顺序表
  147. void ClearList(SqList &L) {
  148. L.length = 0;
  149. }
  150. //********************************功能函数*****************************************//
  151. //输出功能函数 按位置从小到大输出顺序表所有元素
  152. void PrintList(SqList L)
  153. {
  154. printf( "当前顺序表所有元素:");
  155. for ( int i = 0; i<L.length; i++)
  156. {
  157. printf( "%d ", L.data[i]);
  158. }
  159. printf( "\n");
  160. }
  161. //创建顺序表函数
  162. void Create(SqList &L)
  163. {
  164. int n; bool flag;
  165. L.length = 0;
  166. printf( "请输入要创建的顺序表长度(>1):");
  167. scanf( "%d", &n);
  168. printf( "请输入%d个数(空格隔开):", n);
  169. flag = CreateList(L, n);
  170. if (flag) {
  171. printf( "创建成功!\n");
  172. PrintList(L);
  173. }
  174. else printf( "输入长度非法!\n");
  175. }
  176. //插入功能函数 调用InsertList完成顺序表元素插入 调用PrintList函数显示插入成功后的结果
  177. void Insert(SqList &L)
  178. {
  179. int place; ElemType e; bool flag;
  180. printf( "请输入要插入的位置(从1开始)及元素:\n");
  181. scanf( "%d%d", &place, &e);
  182. flag = InsertList(L, place, e);
  183. if (flag)
  184. {
  185. printf( "插入成功!!!\n");
  186. PrintList(L);
  187. }
  188. }
  189. //删除功能函数 调用ListDelete函数完成顺序表的删除 调用PrintList函数显示插入成功后的结果
  190. void Delete(SqList &L)
  191. {
  192. int place; bool flag;
  193. printf( "请输入要删除的位置(从1开始):\n");
  194. scanf( "%d", &place);
  195. flag = ListDelete(L, place);
  196. if (flag)
  197. {
  198. printf( "删除成功!!!\n");
  199. PrintList(L);
  200. }
  201. }
  202. //查找功能函数 调用LocateElem查找元素
  203. void Search(SqList L)
  204. {
  205. ElemType e; int flag;
  206. printf( "请输入要查找的值:\n");
  207. scanf( "%d", &e);
  208. flag = LocateElem(L, e);
  209. if (flag)
  210. {
  211. printf( "该元素位置为:%d\n", flag);
  212. }
  213. else
  214. printf( "未找到该元素!\n");
  215. }
  216. //菜单
  217. void menu()
  218. {
  219. printf( "********1.创建 2.插入*********\n");
  220. printf( "********3.删除 4.查找*********\n");
  221. printf( "********5.倒置 6.分奇偶排序***\n");
  222. printf( "********7.输出 8.清空*********\n");
  223. printf( "********9.退出 *********\n");
  224. }
  225. int main()
  226. {
  227. SqList L; int choice;
  228. InitList(L);
  229. while ( 1)
  230. {
  231. menu();
  232. printf( "请输入菜单序号:\n");
  233. scanf( "%d", &choice);
  234. if ( 9 == choice) break;
  235. switch (choice)
  236. {
  237. case 1:Create(L); break;
  238. case 2:Insert(L); break;
  239. case 3:Delete(L); break;
  240. case 4:Search(L); break;
  241. case 5:Reverse(L); break;
  242. case 6:SplitSort(L); break;
  243. case 7:PrintList(L); break;
  244. case 8:ClearList(L); break;
  245. default: printf( "输入错误!!!\n");
  246. }
  247. }
  248. return 0;
  249. }

结果截图:

插入结果截图
删除结果截图
查找结果截图
输出结果截图

---------------------------------------------2018-09-18更新 添加创建函数 菜单有改动-----------------------------------------

                                                                 

 

---------------------------------------------20191012更新 添加Reverse函数--------------------------------------------

根据下方评论,添加了倒置函数,参考stl的Reverse写法


  
  1. template < class _RandomAccessIter>
  2. _STLP_INLINE_LOOP void
  3. __reverse(_RandomAccessIter __first, _RandomAccessIter __last, const random_access_iterator_tag &) {
  4. for (; __first < __last; ++__first)
  5. _STLP_STD::iter_swap(__first, --__last);
  6. }
倒置展示

2019年10月23日更新,应评论区小伙伴的要求,添加了奇偶分开,并排序的函数


  
  1. //奇偶分开并排序
  2. void SplitSort(SqList &L)
  3. {
  4. int Even = 0;
  5. int Odd = L.length - 1;
  6. int i = 0;
  7. int j = L.length - 1;
  8. bool flag = false;
  9. if (L.length)
  10. for (; i < j; i++, j--)
  11. {
  12. while (L.data[i] % 2 != 0)i++;
  13. while (L.data[j] % 2 == 0)j--;
  14. if (L.data[i] % 2 == 0 && L.data[j] % 2 != 0&&i<j)
  15. {
  16. int temp = L.data[i];
  17. L.data[i] = L.data[j];
  18. L.data[j] = temp;
  19. flag = true;
  20. }
  21. if(!flag) //没有交换
  22. {
  23. Even = L.length - 1; //全奇数
  24. Odd = 0; //全偶数
  25. }
  26. }
  27. if (flag)
  28. {
  29. for( int i= 0;i<L.length;i++)
  30. if (L.data[i] % 2 == 0)
  31. {
  32. Odd = i;
  33. Even = i - 1;
  34. break;
  35. }
  36. }
  37. sort(L.data, L.data + Even + 1);
  38. sort(L.data + Odd, L.data + L.length);
  39. }
测试全奇偶

 

有奇偶

代码已更新至上方全部代码!!!

-------------------------20200819修改 添加ClearList-------------------------------------

代码由评论区用户__BlackHole提供,已更新至上方全部代码。

至于销毁,我是使用的静态分配,如果是new(delete释放)或malloc(free释放)的话,需要释放空间,其实就是堆和栈的区别。

堆和栈的区别就是申请方式不同:栈是系统自动分配空间,而堆则是程序员根据需要申请空间。由于栈上的空间是自动分配自动回收的,所以,栈内数据的生存周期只是在函数的运行过程中,运行后就释放掉。而堆上的数据只要程序员不释放空间,就一直可以访问到,缺点是一旦忘记释放会造成内存泄露。

综上,我写的顺序表不需要进行销毁,当然,顺序表最大长度也固定了,各有利弊,如果是动态分配的话记得释放空间呀!

更多数据结构与算法的实现:数据结构(严蔚敏版)与算法的实现(含全部代码)

本人b站账号:lady_killer9

有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。


转载:https://blog.csdn.net/lady_killer9/article/details/82695770
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场