姓名:Far_Rainbow
    学号: 202505000X
    专业: 软件工程
    年级:2020级

    实验名称:实验2 基于顺序表的非递减有序表的合并

    实验内容

    (1)实验目的
    通过该实验,深入理解顺序表的逻辑结构、物理结构等概念,掌握顺序表基本操作的编程实现,注意顺序表插入、删除等操作过程中数据元素的移动现象,培养学生编写程序时,要考虑程序的健壮性,全面考虑问题,熟练掌握通过函数参数返回函数结果的办法。

    (2)实验内容
    编程实现顺序表下教材第二章定义的线性表的基本操作,并根据已经实现的基本操作,实现两个非递减有序的线性表的合并,注意,合并时,如果有重复的元素(一个表内部的重复元素和两个表之间的重复元素),请保留一个。

    (3)实验要求

    • 求前驱是指,输入一个元素值(而不是位置),求该元素在顺序表中的直接前驱元素值。求后继是指:输入一个元素值(而不是位置),求该元素在顺序表中的直接后继元素值;
    • 为了方便修改数据元素的类型,请使用类型重定义,可以方便修改线性表中的数据元素的类型;
    • 大部分函数的返回结果应是函数执行是否成功的一种状态,执行成功了,才返回具体的结果值;
    • 对每个功能进行测试时,要求把不合法的情况也测试一下。具体见下面的测试用例;
    • 采用菜单形式对应各个操作,使其编成一个完整的小软件,参考界面如下。注意:程序运行过程中菜单不要做成刷屏的效果,测试过的数据不要清除,这样方便截图和查看。

    (4)验收/测试用例
    通过菜单调用各个操作,测试点:

    • 没有初始化前进行其他操作,程序是否能控制住;即,如果没有初始化线性表,其他的功能是无法正常进行的,如果选择进行其他操作,要提示先进行初始化;
    • 先选择菜单1,初始化一个顺序表(初始化顺序表,是指初始化一个空的线性表,里面的元素个数是0);
    • 选择菜单10,插入数据(位置, 数据),要测插入位置不合法的情况(0,1)、(2,1),正确插入3个数据(1,20)、(1,10)、(3,30);
    • 显示顺序表中的数据,屏幕输出10, 20, 30;
    • 判空,屏幕输出顺序表非空;
    • 输出顺序表长度,屏幕输出3;
    • 获取指定位置元素,要测指定位置在【1,3】范围之外的情况和之内的情况;
    • 定位,输入:40, 输出:不存在,输入20,输出位置为2;
    • 求直接前驱,要测求第一个元素的前驱、不存在顺序表中的元素的直接前驱,其他元素的直接前驱;输入10,输出:第一个元素没有前驱,输入20,输出前驱是10,输入40,输出该元素不存在;
    • 求直接后继,要测最后一个元素的后继、不存在顺序表中的元素的直接后继,其他元素的直接后继;同上求前驱;
    • 删除,要测位置在【1,3】范围之外的情况和之内的情况;
    • 清空操作后再测长度,判断是否为空;清空后,测试菜单6到11的功能,看是否能够正确提示。
    • 销毁顺序表,销毁线性表之后还能不能做插入,删除等操作,如果选其他操作,就要提示线性表已经销毁不存在;
    • 测试合并操作,第一个线性表中的元素是(2,3,3,4,5),第二个线性表中的内容是(1,4,5,6,6,7),合并后的结果,请输出。

    实验类型:验证性

    实验的重难点:顺序表的定义和实现,销毁和清空的区别、 两个非递减有序表的去重合并

    实验环境:TDM-GCC 4.9.2 64-bit

    实验步骤及完成任务情况

    一、设计思想

    1. 采用模板实现泛型编程,可创建任意数据类型的顺序表;
    2. 采用动态内存分配的方式管理顺序表的容量,在顺序表内存空间不够时通过expend()函数扩容;
    3. 体会顺序表插入删除时间复杂度都是实验2 基于顺序表的非递减有序表的合并 - 图1#card=math&code=O%28n%29&id=I9Snm)的特点

    二、主要源代码

    1. #include <iostream>
    2. #define SEQUENCESIZE 1000
    3. #define SEQUENCEINCREMENT 500
    4. using std::cin;
    5. using std::cout;
    6. using std::endl;
    7. template <typename T> class Sequence {
    8. private:
    9. T* elem;
    10. int _length;
    11. int _capacity;
    12. void expand();
    13. public:
    14. Sequence() {elem = NULL; _length = 0; }
    15. Sequence(T arr[], int size)
    16. {init(); for (int i = 0; i < size; ++ i) elem[i] = arr[i]; _length = size; }
    17. ~Sequence() {destroy(); }
    18. void init();
    19. void destroy();
    20. void clear() {_length = 0; }
    21. T operator[](int pos) {return elem[pos]; }
    22. bool isempty() const {return _length > 0 ? 0 : 1; }
    23. bool exist() const {return elem > 0 ? 1 : 0; }
    24. int getlength() const {return _length; }
    25. bool getelem(int pos, T& e) const
    26. {if(pos > _length + 1 || pos < 1) return false; e = elem[pos-1]; return true; }
    27. int elemlocate(T const& e) const
    28. {for(int i = 0; i < _length; ++ i) if(elem[i] == e) return i+1; return -1;}
    29. bool priorelem(T const& e, int& pos);
    30. bool nextelem(T const& e, int& pos);
    31. bool insert(T const& e, int pos);
    32. bool remove(T& e, int pos);
    33. void push(T const& e);
    34. T pop() {-- _length; return _length + 1; }
    35. void traverse() const
    36. {for(int i = 0; i < _length; i ++) cout<<elem[i]<<' '; }
    37. void merge(Sequence<T>& Sa, Sequence<T>& Sb);
    38. };
    39. template <typename T> void Sequence<T>::init()
    40. {
    41. elem = new T[SEQUENCESIZE];
    42. _capacity = SEQUENCESIZE;
    43. }
    44. template <typename T> void Sequence<T>::destroy()
    45. {
    46. if (!exist()) return;
    47. delete[] elem;
    48. elem = NULL;
    49. _length = 0;
    50. _capacity = 0;
    51. }
    52. template <typename T> void Sequence<T>::expand()
    53. {
    54. T* newelem = new T[_capacity+SEQUENCEINCREMENT];
    55. for(int i = 0; i < _length; ++ i) newelem[i] = elem[i];
    56. delete[] elem;
    57. elem = newelem;
    58. }
    59. template <typename T> bool Sequence<T>::priorelem(T const& e, int& pos)
    60. {
    61. int i = elemlocate(e);
    62. if (i < 2 || i > _length) return false;
    63. pos = i - 1;
    64. return true;
    65. }
    66. template <typename T> bool Sequence<T>::nextelem(T const& e, int& pos)
    67. {
    68. int i = elemlocate(e);
    69. if (i < 1 || i > _length - 1) return false;
    70. pos = i + 1;
    71. return true;
    72. }
    73. template <typename T> bool Sequence<T>::insert(T const& e, int pos)
    74. {
    75. if (pos < 1 || pos > _length + 1) return false;
    76. if (_capacity < _length + 1) expand();
    77. for(int j = _length - 1; j >= pos - 1; -- j) // 最开始写成j>i-1了,debug了好几个小时,血的教训
    78. elem[j+1] = elem[j];
    79. elem[pos-1] = e;
    80. ++ _length;
    81. return true;
    82. }
    83. template <typename T> bool Sequence<T>::remove(T& e, int pos)
    84. {
    85. if(pos < 1 || pos > _length) return false;
    86. e = elem[pos-1];
    87. for(int j = pos - 1; j < _length - 1; ++ j)
    88. elem[j] = elem[j+1];
    89. -- _length;
    90. return true;
    91. }
    92. template <typename T> void Sequence<T>::push(T const& e)
    93. {
    94. if (_capacity < _length + 1) expand();
    95. elem[_length] = e;
    96. ++ _length;
    97. }
    98. template <typename T> void Sequence<T>::merge(Sequence<T>& Sa, Sequence<T>& Sb)
    99. {
    100. int i = 0, j = 0, k = 0;
    101. while(i < Sa._length && j < Sb._length) { //不能 <= ,否则会数组下标越界
    102. if (Sa[i] < Sb[j]) elem[k++] = Sa[i++];
    103. else if (Sa[i] > Sb[j]) elem[k++] = Sb[j++];
    104. else if (Sa[i] == Sb[j++]) elem[k++] = Sa[i++]; // 去重
    105. }
    106. while (i < Sa._length) elem[k++] = Sa[i++];
    107. while (j < Sb._length) elem[k++] = Sb[j++];
    108. _length = k;
    109. }
    110. int main()
    111. {
    112. cout<<"\n 基于顺序表的非递减有序表的合并\n\n";
    113. cout<<"1---初始化一个线性表\n";
    114. cout<<"2---销毁线性表\n";
    115. cout<<"3---清空线性表\n";
    116. cout<<"4---判断线性表是否为空\n";
    117. cout<<"5---求线性表长度\n";
    118. cout<<"6---获取线性表中指定位置的元素\n";
    119. cout<<"7---获取线性表元素的位置\n";
    120. cout<<"8---求前驱\n";
    121. cout<<"9---求后继\n";
    122. cout<<"10--在线性表指定位置插入元素\n";
    123. cout<<"11--删除线性表指定位置的元素\n";
    124. cout<<"12--显示线性表\n";
    125. cout<<"13--合并两个非递减有序线性表\n";
    126. cout<<"\n\t退出,输入一个负数!\n\n";
    127. Sequence<int> Se;
    128. while(true)
    129. {
    130. int myOption;
    131. cout<<"\n请输入操作序号:";
    132. cin>>myOption;
    133. switch(myOption){
    134. case 1:{
    135. if(Se.exist()){
    136. cout<<"初始化失败,顺序表已存在!\n";
    137. break;
    138. }
    139. Se.init();
    140. cout<<"初始化成功!\n";
    141. break;
    142. }
    143. case 2:{
    144. if (!Se.exist()){
    145. cout<<"销毁失败,顺序表不存在\n";
    146. break;
    147. }
    148. Se.destroy();
    149. cout<<"销毁成功!\n";
    150. break;
    151. }
    152. case 3:{
    153. if (!Se.exist()){
    154. cout<<"清空失败,顺序表不存在\n";
    155. break;
    156. }
    157. if (Se.isempty()) ;
    158. else Se.clear();
    159. cout<<"清空成功!\n";
    160. break;
    161. }
    162. case 4:{
    163. if (!Se.exist()){
    164. cout<<"判空失败,顺序表不存在\n";
    165. break;
    166. }
    167. if (Se.isempty()) cout<<"顺序表为空!\n";
    168. else cout<<"顺序表非空!\n";
    169. break;
    170. }
    171. case 5:{
    172. if (!Se.exist()){
    173. cout<<"请先创建顺序表!\n";
    174. break;
    175. }
    176. cout<<"顺序表的长度是"<<Se.getlength()<<endl;
    177. break;
    178. }
    179. case 6:{
    180. if (!Se.exist()){
    181. cout<<"顺序表不存在,请先创建顺序表!\n";
    182. break;
    183. }
    184. if (Se.isempty()){
    185. cout<<"顺序表为空,请先插入元素!\n";
    186. break;
    187. }
    188. cout<<"请输入你要获取元素的位置:";
    189. int pos, e;
    190. cin>>pos;
    191. if (!Se.getelem(pos, e)) {
    192. cout<<"不存在该位置的元素\n";
    193. break;
    194. }
    195. cout<<"第"<<pos<<"位元素是 "<<e<<endl;
    196. break;
    197. }
    198. case 7:{
    199. if (!Se.exist()){
    200. cout<<"顺序表不存在,请先创建顺序表!\n";
    201. break;
    202. }
    203. if (Se.isempty()){
    204. cout<<"顺序表为空,请先插入元素!\n";
    205. break;
    206. }
    207. cout<<"请输入您要获取位置的元素:";
    208. int e;
    209. cin>>e;
    210. if (!Se.elemlocate(e)){
    211. cout<<"顺序表中不存在该元素!\n";
    212. break;
    213. }
    214. cout<<"元素"<<e<<"的位置是"<<Se.elemlocate(e)<<endl;
    215. break;
    216. }
    217. case 8:{
    218. if (!Se.exist()){
    219. cout<<"顺序表不存在,请先创建顺序表!\n";
    220. break;
    221. }
    222. if (Se.isempty()){
    223. cout<<"顺序表为空,请先插入元素!\n";
    224. break;
    225. }
    226. cout<<"请输入您要获取前驱的元素:";
    227. int pos, e;
    228. cin>>e;
    229. if (!Se.priorelem(e, pos)){
    230. cout<<"获取失败,该元素不存在或无前驱!";
    231. break;
    232. }
    233. cout<<"元素"<<e<<"的前驱元素是"<<Se[pos-1]<<endl;
    234. break;
    235. }
    236. case 9:{
    237. if (!Se.exist()){
    238. cout<<"顺序表不存在,请先创建顺序表!\n";
    239. break;
    240. }
    241. if (Se.isempty()){
    242. cout<<"顺序表为空,请先插入元素!\n";
    243. break;
    244. }
    245. cout<<"请输入您要获取后继的元素:";
    246. int pos, e;
    247. cin>>e;
    248. if (!Se.nextelem(e, pos)){
    249. cout<<"获取失败,该元素不存在或无后继!";
    250. break;
    251. }
    252. cout<<"元素"<<e<<"的后继元素是"<<Se[pos-1]<<endl;
    253. break;
    254. }
    255. case 10:{
    256. if (!Se.exist()){
    257. cout<<"顺序表不存在,请先创建顺序表!\n";
    258. break;
    259. }
    260. cout<<"请输入指定位置:";
    261. int pos;
    262. cin>>pos;
    263. cout<<"请输入想要插入的值:";
    264. int e;
    265. cin>>e;
    266. if (!Se.insert(e, pos)){
    267. cout<<"插入失败,请重新尝试!\n";
    268. break;
    269. }
    270. else cout<<"插入完毕!\n";
    271. break;
    272. }
    273. case 11:{
    274. if (!Se.exist()){
    275. cout<<"顺序表不存在,请先创建顺序表!\n";
    276. break;
    277. }
    278. if (Se.isempty()){
    279. cout<<"顺序表为空!\n";
    280. break;
    281. }
    282. cout<<"请输入你要删除的元素的位置:";
    283. int pos;
    284. cin>>pos;
    285. int e;
    286. if (!Se.remove(e, pos)){
    287. cout<<"删除失败,请重新尝试!\n";
    288. break;
    289. }
    290. else cout<<"删除完毕!"<<"被删除的元素是"<<e<<endl;;
    291. break;
    292. }
    293. case 12:{
    294. if (!Se.exist()){
    295. cout<<"顺序表不存在,请先创建顺序表!\n";
    296. break;
    297. }
    298. if (Se.isempty()){
    299. cout<<"顺序表为空!\n";
    300. break;
    301. }
    302. cout<<"顺序表的所有元素是:";
    303. Se.traverse();
    304. cout<<endl;
    305. break;
    306. }
    307. case 13:{
    308. int a[5] = {17, 21, 39, 40, 56};
    309. int b[8] = {10, 20, 30, 40, 50, 60, 70, 80};
    310. Sequence<int> Sa(a, 5);
    311. Sequence<int> Sb(b, 8);
    312. cout<<"顺序表Sa的所有元素是:";
    313. Sa.traverse();
    314. cout<<endl;
    315. cout<<"顺序表Sb的所有元素是:";
    316. Sb.traverse();
    317. cout<<endl;
    318. Sequence<int> Sc;
    319. Sc.init();
    320. Sc.merge(Sa, Sb);
    321. cout<<"\n合并Sa和Sb为Sc";
    322. cout<<"顺序表Sa的所有元素是:";
    323. Sc.traverse();
    324. cout<<endl;
    325. break;
    326. }
    327. }
    328. if(myOption >13) cout<<"\n请输入小于13的正整数\n\n";
    329. if(myOption < 0){
    330. cout<<"\n退出程序!\n";
    331. break;
    332. }
    333. }
    334. return 0;
    335. }

    实验结果
    实验2 基于顺序表的非递减有序表的合并 - 图2
    实验2 基于顺序表的非递减有序表的合并 - 图3
    实验2 基于顺序表的非递减有序表的合并 - 图4