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

    实验名称:实验3 单链表的基本操作实现

    实验内容

    (1)实验目的
    通过该实验,深入理解链表的逻辑结构、物理结构等概念,掌握链表基本操作的编程实现,熟练掌握C语言中指针的操作。和实验2对比,掌握线性结构两种不同存储方式的区别。

    (2)实验内容
    编程实现链表下教材第二章定义的线性表的基本操作,最好用菜单形式对应各个操作,使其编程一个完整的小软件。注意,每个功能模块一定要考虑非法的情况,并作出相应的提示,例如:求前驱,要分别能够测试第一个元素的前驱、其他正常的元素的前驱、输入一个在表中不存在的元素求其前驱,这三种情况应给出相应的提示语和结果值;插入和删除时要考虑插入或删除的位置是否合法等。

    (3)实验要求:
    菜单项包括:

    1. 初始化或重置链表
    2. 销毁链表
    3. 清空链表
    4. 链表长度
    5. 指定位置的元素值
    6. 链表已存在元素的位序
    7. 求输入元素的直接前驱
    8. 求输入元素的直接后继
    9. 在第i个位置插入一个元素
    10. 删除第i个元素
    11. 输出有的链表元素
    12. 初始化并用头插法(或尾插法)输入元素
    13. 实现单链表的逆序存放
      要求:所有的提示语和输出语句不允许出现在自定义的函数中,只能在main函数中出现提示语。
      注:销毁链表时需要循环释放每个结点所占用的空间。
      注:求前驱是指,输入一个元素值(而不是位置),求该元素在顺序表中的直接前驱元素值。求后继是指:输入一个元素值(而不是位置),求该元素在顺序表中的直接后继元素值。

    (4)验收/测试用例
    参考实验2

    实验类型:验证性

    实验的重难点:链表的定义和实现

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

    实验步骤及完成任务情况

    一、设计思想

    1. 采用模板实现泛型编程,可创建任意数据类型的单链表;
    2. 采用链式存储方式,插入删除时间复杂度都是实验3 单链表的基本操作实现 - 图1#card=math&code=O%281%29&id=uXxHU)

    二、主要源代码

    1. #include <iostream>
    2. using std::cin;
    3. using std::cout;
    4. using std::endl;
    5. template <typename T> struct Lnode {
    6. T data;
    7. Lnode<T>* next;
    8. };
    9. template <typename T> class List {
    10. private:
    11. int _length;
    12. Lnode<T>* header;
    13. public:
    14. void init() {header = new Lnode<T>; header->next = NULL; _length = 0;}
    15. void destroy();
    16. void clear();
    17. List() {header = NULL; }
    18. ~List() {destroy(); }
    19. bool exist() const {return header != NULL ? 1 : 0;}
    20. bool isempty() const {return _length > 0 ? 0 : 1; }
    21. int getlength() const {return _length; }
    22. Lnode<T>* find(int pos);
    23. int elemlocate(T const& e);
    24. Lnode<T>* priornode(T const& e);
    25. Lnode<T>* nextnode(T const& e);
    26. Lnode<T>* insert(int pos, T const& e);
    27. T remove(int pos);
    28. void traverse();
    29. void create(int n);
    30. Lnode<T>* reverse();
    31. };
    32. template <typename T> void List<T>::destroy()
    33. {
    34. if (!exist()) return;
    35. Lnode<T>* p = header, *q;
    36. while(p){
    37. q = p->next;
    38. delete p;
    39. p = q;
    40. }
    41. header = NULL;
    42. _length = 0;
    43. }
    44. template <typename T> void List<T>::clear()
    45. {
    46. Lnode<T>* p = header->next, *q;
    47. while(p){
    48. q = p->next;
    49. delete p;
    50. p = q;
    51. }
    52. _length = 0;
    53. }
    54. template <typename T> Lnode<T>* List<T>::find(int pos)
    55. {
    56. int count = 0;
    57. Lnode<T>* p = header->next;
    58. while(p){
    59. count ++;
    60. if(count == pos) return p;
    61. p = p->next;
    62. }
    63. return NULL;
    64. }
    65. template <typename T> int List<T>::elemlocate(T const& e)
    66. {
    67. int count = 0;
    68. Lnode<T>* p = header->next;
    69. while(p)
    70. {
    71. count ++;
    72. if(p->data == e) return count;
    73. p = p->next;
    74. }
    75. return 0;
    76. }
    77. template <typename T> Lnode<T>* List<T>::priornode(T const& e) //////
    78. {
    79. Lnode<T>* p = header->next, *q;
    80. while(p)
    81. {
    82. q = p->next;
    83. if(q && q->data == e) return p;
    84. p = q;
    85. }
    86. return NULL;
    87. }
    88. template <typename T> Lnode<T>* List<T>::nextnode(T const& e) //////
    89. {
    90. Lnode<T>* p =header->next, *q;
    91. while(p){
    92. q = p->next;
    93. if(q && p->data == e) return q;
    94. p = q;
    95. }
    96. return NULL;
    97. }
    98. template <typename T> Lnode<T>* List<T>::insert(int pos, T const& e)
    99. {
    100. int count = 0;
    101. Lnode<T>* p = header; //注意考虑插入到首元结点的位置,故不用p=header->next;
    102. Lnode<T>* q = new Lnode<T>;
    103. q->data = e;
    104. while(p){
    105. count ++;
    106. if(count == pos){
    107. q->next = p->next;
    108. p->next = q;
    109. ++ _length;
    110. return q;
    111. }
    112. p = p->next;
    113. }
    114. return NULL;
    115. }
    116. template <typename T> T List<T>::remove(int pos) // 删不了第一个元素 和非法情况
    117. {
    118. int count = 0;
    119. Lnode<T>* p = header->next, *q;
    120. while(p)
    121. {
    122. q = p->next;
    123. count ++;
    124. if(count == pos-1){
    125. p->next = q->next;
    126. T e = q->data;
    127. delete q;
    128. -- _length;
    129. return e ;
    130. }
    131. p = q;
    132. }
    133. }
    134. template <typename T> void List<T>::traverse()
    135. {
    136. Lnode<T>* p = header->next;
    137. while(p){
    138. cout<<p->data<<' ';
    139. p = p->next;
    140. }
    141. }
    142. template <typename T> void List<T>::create(int n)
    143. {
    144. Lnode<T>* p;
    145. while(n --)
    146. {
    147. p = new Lnode<T>;
    148. cout<<"请输入想要插入的值:";
    149. cin>>p->data;
    150. p->next = header->next;
    151. header->next = p;
    152. ++ _length;
    153. }
    154. }
    155. template <typename T> Lnode<T>* List<T>::reverse()
    156. {
    157. if(header == NULL || header->next == NULL) return header;
    158. Lnode<T>* now = header->next, *pre = NULL, *next = NULL;
    159. while(now){
    160. next = now->next;
    161. now->next = pre;
    162. pre = now;
    163. now = next;
    164. }
    165. header->next = pre;
    166. return header;
    167. }
    168. int main()
    169. {
    170. cout<<"\n 基单链表的基本操作实现\n\n";
    171. cout<<"1---初始化一个单链表\n";
    172. cout<<"2---销毁单链表\n";
    173. cout<<"3---清空单链表\n";
    174. cout<<"4---求单链表长度\n";
    175. cout<<"5---获取线性表中指定位置的元素\n";
    176. cout<<"6---获取单链表元素的位置\n";
    177. cout<<"7---求前驱\n";
    178. cout<<"8---求后继\n";
    179. cout<<"9---在单链表指定位置插入元素\n";
    180. cout<<"10--删除单链表指定位置的元素\n";
    181. cout<<"11--显示单链表\n";
    182. cout<<"12--初始化并用头插法输入元素\n";
    183. cout<<"13--实现单链表的逆序存放\n";
    184. cout<<"\n\t退出,输入一个负数!\n\n";
    185. List<int> L;
    186. while(true)
    187. {
    188. int myOption;
    189. cout<<"\n请输入操作序号:";
    190. cin>>myOption;
    191. switch(myOption){
    192. case 1:{
    193. if(L.exist()){
    194. cout<<"初始化失败,单链表已存在!\n";
    195. break;
    196. }
    197. L.init();
    198. cout<<"初始化成功!\n";
    199. break;
    200. }
    201. case 2:{
    202. if (!L.exist()){
    203. cout<<"销毁失败,单链表不存在\n";
    204. break;
    205. }
    206. L.destroy();
    207. cout<<"销毁成功!\n";
    208. break;
    209. }
    210. case 3:{
    211. if (!L.exist()){
    212. cout<<"清空失败,单链表不存在\n";
    213. break;
    214. }
    215. if (L.isempty()) ;
    216. else L.clear();
    217. cout<<"清空成功!\n";
    218. break;
    219. }
    220. case 4:{
    221. if (!L.exist()){
    222. cout<<"请先创建单链表!\n";
    223. break;
    224. }
    225. cout<<"单链表的长度是"<<L.getlength()<<endl;
    226. break;
    227. }
    228. case 5:{
    229. if (!L.exist()){
    230. cout<<"单链表不存在,请先创建单链表!\n";
    231. break;
    232. }
    233. if (L.isempty()){
    234. cout<<"单链表为空,请先插入元素!\n";
    235. break;
    236. }
    237. cout<<"请输入你要获取元素的位置:";
    238. int pos;
    239. cin>>pos;
    240. Lnode<int>* ptr = L.find(pos);
    241. if (!ptr) {
    242. cout<<"不存在该位置的元素\n";
    243. break;
    244. }
    245. cout<<"第"<<pos<<"位元素是 "<<ptr->data<<endl;
    246. break;
    247. }
    248. case 6:{
    249. if (!L.exist()){
    250. cout<<"单链表不存在,请先创建单链表!\n";
    251. break;
    252. }
    253. if (L.isempty()){
    254. cout<<"单链表为空,请先插入元素!\n";
    255. break;
    256. }
    257. cout<<"请输入您要获取位置的元素:";
    258. int e;
    259. cin>>e;
    260. if (!L.elemlocate(e)){
    261. cout<<"单链表中不存在该元素!\n";
    262. break;
    263. }
    264. cout<<"元素"<<e<<"的位置是"<<L.elemlocate(e)<<endl;
    265. break;
    266. }
    267. case 7:{
    268. if (!L.exist()){
    269. cout<<"单链表不存在,请先创建单链表!\n";
    270. break;
    271. }
    272. if (L.isempty()){
    273. cout<<"单链表为空,请先插入元素!\n";
    274. break;
    275. }
    276. cout<<"请输入您要获取前驱的元素:";
    277. int pos, e;
    278. cin>>e;
    279. Lnode<int>* ptr = L.priornode(e);
    280. if (!ptr){
    281. cout<<"获取失败,该元素不存在或无前驱!\n";
    282. break;
    283. }
    284. cout<<"元素"<<e<<"的前驱元素是"<<(ptr-1)->data<<endl;
    285. break;
    286. }
    287. case 8:{
    288. if (!L.exist()){
    289. cout<<"单链表不存在,请先创建单链表!\n";
    290. break;
    291. }
    292. if (L.isempty()){
    293. cout<<"单链表为空,请先插入元素!\n";
    294. break;
    295. }
    296. cout<<"请输入您要获取后继的元素:";
    297. int e;
    298. cin>>e;
    299. Lnode<int>* ptr = L.nextnode(e);
    300. if (!ptr){
    301. cout<<"获取失败,该元素不存在或无后继!\n";
    302. break;
    303. }
    304. cout<<"元素"<<e<<"的后继元素是"<<(ptr+1)->data<<endl;
    305. break;
    306. }
    307. case 9:{
    308. if (!L.exist()){
    309. cout<<"单链表不存在,请先创建单链表!\n";
    310. break;
    311. }
    312. cout<<"请输入指定位置:";
    313. int pos;
    314. cin>>pos;
    315. cout<<"请输入想要插入的值:";
    316. int e;
    317. cin>>e;
    318. if (!L.insert(pos, e)){
    319. cout<<"插入失败,请重新尝试!\n";
    320. break;
    321. }
    322. else cout<<"插入完毕!\n";
    323. break;
    324. }
    325. case 10:{
    326. if (!L.exist()){
    327. cout<<"单链表不存在,请先创建单链表!\n";
    328. break;
    329. }
    330. if (L.isempty()){
    331. cout<<"单链表为空!\n";
    332. break;
    333. }
    334. cout<<"请输入你要删除的元素的位置:";
    335. int pos;
    336. cin>>pos;
    337. int e = L.remove(pos);
    338. if (!e){
    339. cout<<"删除失败,请重新尝试!\n";
    340. break;
    341. }
    342. else cout<<"删除完毕!"<<"被删除的元素是"<<e<<endl;;
    343. break;
    344. }
    345. case 11:{
    346. if (!L.exist()){
    347. cout<<"单链表不存在,请先创建单链表!\n";
    348. break;
    349. }
    350. if (L.isempty()){
    351. cout<<"单链表为空!\n";
    352. break;
    353. }
    354. cout<<"单链表的所有元素是:";
    355. L.traverse();
    356. cout<<endl;
    357. break;
    358. }
    359. case 12:{
    360. if (!L.exist()){
    361. cout<<"单链表不存在,请先创建单链表!\n";
    362. break;
    363. }
    364. cout<<"请输入你想插入的元素个数:";
    365. int n;
    366. cin>>n;
    367. L.create(n);
    368. break;
    369. }
    370. case 13:{
    371. if (!L.exist()){
    372. cout<<"单链表不存在,请先创建单链表!\n";
    373. break;
    374. }
    375. if (L.isempty()){
    376. cout<<"单链表为空!\n";
    377. break;
    378. }
    379. cout<<"逆置前的单链表为:";
    380. L.traverse();
    381. cout<<endl<<"逆置后的单链表为:";
    382. L.reverse();
    383. L.traverse();
    384. cout<<endl;
    385. break;
    386. }
    387. }
    388. if(myOption >13 || myOption == 0) cout<<"\n请输入小于13的正整数\n\n";
    389. if(myOption < 0){
    390. cout<<"\n退出程序!\n";
    391. break;
    392. }
    393. }
    394. return 0;
    395. }