递归实现单链表的各种基本操作

  1 #include<iostream>
  2 using namespace std;
  3
  4 #define OK 1
  5 #define ERROR 0
  6 typedef int Status;
  7
  8 typedef struct LNode
  9 {
 10     int data;    //结点的数据域
 11     struct LNode *next;        //结点的指针域
 12 }LNode, *LinkList;  //LinkList为指向结构体LNode的指针类型
 13
 14 void create_List(LinkList &L, int n){   //法1:递归初始化创建n个节点
 15     if (n == 0)return;//创建n个节点
 16     else{  //此时传进来的是第一个节点的指针
 17         L = new LNode;  //指针指向新生成的节点
 18         cin >> L->data;    //输入数据,将其压栈
 19         L->next = NULL;   //尾插法,先将下一个指针域赋为NULL
 20         create_List(L->next, n - 1);   //递归创建n个节点
 21     }
 22 }
 23
 24 Status Creat_LinkList(LinkList &L){    //法2:创建链表,当输入数字为-1时,令当前指针为空
 25     int num;
 26     cout << "请每行输入一个数据元素并按回车(直到-1退出):";
 27     cin >> num;//输入数据
 28     if (num == -1){ L = NULL; return OK; } //结束
 29     else{
 30         L = new LNode;  //申请新的节点,指针指向结构体
 31         L->data = num;   //先将数据放到数据域
 32         return Creat_LinkList(L->next);   //递归创建节点
 33     }
 34 }
 35
 36 int count_LNode(LinkList L){     //统计节点个数,传入链表首地址
 37     if (L == NULL)return 0;     //递归结束条件,递归到尾节点的下一个节点,直接返回
 38     else return count_LNode(L->next) + 1;    //否则继续指向下一个节点,表长加1
 39 }
 40
 41 void lprint_LNode(LinkList L){     //正序打印链表
 42     if (L == NULL)return;            //递归的结束条件
 43     else{
 44         cout << L->data << ‘ ‘;    //先打印当前节点的数据
 45         lprint_LNode(L->next);    //再递归循环链表
 46     }
 47 }
 48
 49 void bprint_LNode(LinkList L){    //反序打印链表
 50     if (L == NULL)return;     //递归的结束条件
 51     else{
 52         bprint_LNode(L->next);      //先递归循环链表,将数据域压入栈中
 53         cout << L->data << ‘ ‘;      //讲数据出栈并打印
 54     }
 55 }
 56
 57 int maxVal_List(LinkList L)   //求表中元素的最大值
 58 {
 59     int maxVal;
 60     if (L->next == NULL)  //如果到尾节点,就把当前节点的值赋值为maxVal
 61         return L->data;  //递归结束条件,出栈比较
 62     else{
 63         maxVal = maxVal_List(L->next);//先把一个个数据压栈
 64         if (L->data > maxVal)
 65             maxVal = L->data;
 66         return maxVal;
 67     }
 68
 69 }
 70
 71 int minVal_List(LinkList L)   //求表中元素的最大值
 72 {
 73     int minVal;
 74     if (L->next == NULL)  //如果到尾节点,就把当前节点的值赋值为maxVal
 75         return L->data;  //返回末尾的值赋给尾节点
 76     else{
 77         minVal = minVal_List(L->next);//先把一个个数据压栈
 78         if (L->data < minVal)
 79             minVal = L->data;
 80         return minVal;   //返回上一层
 81     }
 82 }
 83
 84 int getSum_List(LinkList L){   //递归求该表中所有元素的和
 85     if (L == NULL)return 0;      //递归结束条件:当p指向空时,返回0
 86     else        //否则将当前指针指向的数据域压入栈中,递归到链表尾
 87         return getSum_List(L->next) + L->data;
 88 }
 89
 90 bool found = false;
 91 void Print_List(LinkList L, int val){  //12.打印单链表中从某节点元素开始后的所有节点
 92     if (!L)return; //递归结束条件
 93     else{
 94         if (L->data == val)found = true;
 95         if (found)cout << L->data << ‘ ‘;  //只要从满足那一节点之后,打印该点之后的所有节点
 96         Print_List(L->next, val);  //递归
 97     }
 98 }
 99
100 bool flag = false;//用来标记是否查找成功
101 void PriorElem_List(LinkList L, int val,int &preVal){   //9.求某元素的前驱元素,引用前驱元素
102     if (!L || L->data == val){  //当输入val刚好是第一个节点的时候,直接返回
103         preVal = val;
104         return;
105     }
106     else {
107         if (L->next->data == val){
108             preVal = L->data;
109             flag = true;
110         }
111         else
112             PriorElem_List(L->next, val, preVal);//递归查找
113     }
114 }
115
116 LinkList pre =NULL;
117 Status IsOrder_List(LinkList L){  //10.判断单链表是否递增有序
118     if (!L)return OK;  //当遍历到尾节点的下一个位置,返回正确,表示递增有序
119     if (pre && (pre->data > L->data))return ERROR;
120     pre = L;  //将当前节点作为前驱pre节点
121     return IsOrder_List(L->next);  //递归遍历每个节点
122 }
123
124 int j = 1;  //
125 bool flag_insert = false;
126 void insert_List(LinkList &L, int i, int e){ //11.在单链表的第i个位置插入元素e
127     LinkList q;
128     if (i == 1){
129         q = new LNode;
130         q->data = e;//赋值
131         q->next = L;
132         L = q;
133         flag_insert = true;
134     }
135     if (!L || flag_insert)return;   //递归终止条件
136     else {
137         if (j == i-1){
138             q = new LNode; //申请一个新的节点
139             q->data = e;  //接下来的操作按常规来
140             q->next = L->next;
141             L->next = q;
142             flag_insert = true;//表示插入成功
143         }
144         else{
145             j++;  //表长先加1,再递归循环链表
146             insert_List(L->next, i, e);
147         }
148     }
149 }
150
151 bool findVal_list = false;
152 void check_List(LinkList L,int val){//检查val元素是否在表中
153     if (L == NULL || findVal_list)return;  //递归出口,若找到的话就不用递归了
154     else{
155         if (L->data == val)findVal_list=true;  //此时已经找到
156         else check_List(L->next, val);  //继续递归查找
157     }
158 }
159
160 int k = 1;
161 bool delNodeflag = false;
162 void delNode_List(LinkList &L,int i,int &e){ //13.删除单链表的第i个元素
163     if (!L || delNodeflag)return;
164     else{
165         LinkList q;
166         if (i == 1){
167             q = L;
168             e = q->data;
169             L = L->next;
170             delete q;
171             delNodeflag = true;
172         }
173         else if (k == i-1){  //找到要删除节点的前驱
174             q= L->next;  //基本操作
175             e = q->data;
176             L->next = q->next;
177             delete q;
178             delNodeflag = true;    //标记删除成功
179         }
180         else {
181             k++;  //循环链表
182             delNode_List(L->next,i,e); //递归链表
183         }
184     }
185 }
186 int main()
187 {
188     int i,e;
189     int choose;
190
191     LinkList L;
192     choose = -1;
193     while (choose != 0)
194     {
195         cout << "******************************************************************************\n";
196         cout << "  1. 建立空链表;                          2. 输入指定个数的数据元素创建链表\n";
197         cout << "  3. 正序打印表中元素 ;                   4. 逆序打印表中元素\n";
198         cout << "  5. 求表中元素的最大值;                  6. 求表中元素的最小值\n" ;
199         cout << "  7. 返回单链表的长度;                    8. 递归求该表中所有节点元素的和\n";
200         cout << "  9. 查找某元素的前驱元素;                10.判断单链表是否递增有序 \n";
201         cout << "  11.在单链表的第i个位置插入元素e         12.打印单链表中从某节点元素开始后的所有节点\n";
202         cout << "  13.删除单链表的第i个元素                0. 退出\n";
203         cout << "*******************************************************************************\n";
204
205         cout << "请选择:";
206         cin >> choose;
207         switch (choose)
208         {
209         case 1:      //建立空链表
210             L =NULL;//这里不带头结点,建立空链表
211             cout << "成功建立空链表" << endl << endl;
212             break;
213         case 2:     //输入指定个数的数据元素创建链表 ,这里也可以调用当输入不为-1的函数
214             /*cout << "请输入一个数,代表元素的个数:";
215             cin >> i;
216             if (i == 0)
217                 cout << "此时创建的是空链表" << endl<<endl;
218             else{
219                 cout << "请输入" << i << "个数据元素,之间用空格隔开:";
220                 create_List(L, i);
221                 cout << "成功建立单链表" << endl << endl;
222             }    */
223             if (Creat_LinkList(L))   //也可以用第2中创建节点的方法创建单链表,此时实参传入第一个节点的指针
224                 cout << "成功创建单链表" << endl;
225             else
226                 cout << "创建单链表失败" << endl;
227             break;
228         case 3:  //正序打印表中元素
229             if (count_LNode(L)){
230                 cout << "当前表中一共有" << count_LNode(L) << "个元素,正序输出依次为";
231                 lprint_LNode(L);
232                 cout << endl<<endl;
233             }
234             else
235                 cout << "当前为空链表" << endl << endl;
236             break;
237         case 4:     //逆序打印表中元素
238             if (count_LNode(L)){
239                 cout << "当前表中一共有" << count_LNode(L) << "个元素,逆序输出依次为";
240                 bprint_LNode(L);
241                 cout << endl << endl;
242             }
243             else
244                 cout << "当前为空链表" << endl << endl;
245             break;
246         case 5:   //求表中元素的最大值
247             if (count_LNode(L)){
248                 cout << "表中最大的元素为:" << maxVal_List(L) << "。\n" << endl;
249             }
250             else
251                 cout << "当前为空链表" << endl << endl;
252             break;
253         case 6:   //求表中元素的最小值
254             if (count_LNode(L)){
255                 cout << "表中最小的元素为:" << minVal_List(L) << "。\n" << endl;
256             }
257             else
258                 cout << "当前为空链表" << endl << endl;
259             break;
260         case 7:    //返回单链表的长度
261             if (count_LNode(L))
262                 cout << "当前单链表表长为" << count_LNode(L) << "。\n" << endl;
263             else
264                 cout << "当前为空表" << endl << endl;
265             break;
266         case 8:    //递归求该表中所有元素的和
267             if (count_LNode(L))
268                 cout << "当前表中所有元素的和为" << getSum_List(L) << "。\n" << endl;
269             else
270                 cout << "当前为空表" << endl << endl;
271             break;
272         case 9:   //查找某元素的前驱元素
273             if (!L)
274                 cout << "当前为空表" << endl<<endl;
275             else {
276                 int val,preVal;
277                 cout << "请输入一个待查找前驱元素的元素:";
278                 cin >> val;
279                 flag = false;
280                 PriorElem_List(L, val, preVal);
281                 if (flag)
282                     cout << "待查找元素" << val << "的前驱元素为" << preVal << "。\n" << endl;
283                 else
284                     cout << "找不到" << val << "的前驱元素" << endl << endl;
285             }
286             break;
287         case 10: ///判断单链表是否递增有序
288             if (IsOrder_List(L))
289                 cout << "该链表递增有序" << endl << endl;
290             else
291                 cout << "该链表非递增" << endl << endl;
292             break;
293         case 11:  //在单链表的第i个位置后面插入元素e,在这里链表长度至少为1,否则插入失败
294             cout <<"请输入要插入元素的位置及插入的元素分别为(用空格隔开):";
295             cin >> i>> e;
296             if (i<1 || (i>count_LNode(L)+1))
297                 cout << "输入" << i << "不在节点位置范围内。" << endl << endl;
298             else{
299                 flag_insert = false, j = 1;
300                 insert_List(L, i, e);
301                 if (flag_insert)
302                     cout << "成功在第" << i << "个位置插入元素" << e << "。\n" << endl;
303                 else
304                     cout << "插入失败" << endl << endl;
305             }
306             break;
307         case 12: //打印单链表中从某节点元素开始后的所有节点
308             if (!L)
309                 cout << "当前为空表" << endl << endl;
310             else{
311                 int val;
312                 findVal_list=found = false;
313                 cout << "请输入打印的起始元素:";
314                 cin >> val;
315                 check_List(L, val);
316                 if (findVal_list){
317                     cout << "链表元素依次为:";
318                     Print_List(L, val);
319                     cout << endl << endl;
320                 }
321                 else
322                     cout << "该表中没有" << val << "这个元素。" << endl << endl;
323             }
324             break;
325         case 13:  //删除单链表的第i个元素
326             if (!L)
327                 cout << "当前链表为空。" << endl << endl;
328             else{
329                 cout << "请输入要删除节点的位置:";
330                 cin >> i;
331                 if (i<1 || i>count_LNode(L))
332                     cout << "输入" << i << "不在节点位置范围内。" << endl<< endl;
333                 else{
334                     delNodeflag = false,k=1;
335                     delNode_List(L, i, e);
336                     if (delNodeflag)
337                         cout << "成功删除第" << i << "个位置的元素" << e << "。\n" << endl;
338                     else
339                         cout << "删除失败。" << endl << endl;
340                 }
341             }
342             break;
343         }
344     }
345     return 0;
346 }

花了差不多一天时间终于搞懂了递归实现单链表的操作,写代码1h,测试找bug半天。。。~_~"||好好纪念一下。

原文地址:https://www.cnblogs.com/acgoto/p/8716714.html

时间: 2024-12-10 17:54:45

递归实现单链表的各种基本操作的相关文章

递归、非递归 反转单链表

定义链表结构 struct ListNode { int val; ListNode *next; ListNode(int v) : val(v), next(NULL) {} }; 非递归反转单链表 ListNode* reverse(ListNode *root) { if (root == NULL || root->next == NULL) return root; ListNode *cur = root->next; root->next = NULL; while (c

单链表实现及其基本操作

import java.util.HashMap; import java.util.Scanner; import java.util.Stack; /** * * @author kerryfish * 关于java中链表的操作 * 1. 求单链表中结点的个数: getListLength * 2. 将单链表反转: reverseList(遍历),reverseListRec(递归) * 3. 查找单链表中的倒数第K个结点(k > 0): reGetKthNode * 4. 查找单链表的中间

对于&quot;单链表逆置和递归&quot;的问题的理解.

一. 相关知识要点: 学习或了解基础数据结构和C语言, 对基础链表知识或相关知识有概况性认识. 例如: 本题目结构为: 1 #define elem_type int 2 3 typedef struct _single_list { 4 elem_type data; //所存的数据元素 5 _single_list *next; //所存的指针元素 6 }ListNode; 二. 问题的思考过程(本题以3种不同的方法解决): <1>类似于我们学习的C语言基础知识中的冒泡排序(参考C程序设计

单链表的递归与非递归实现

一:递归版本 1 class LinkList 2 { 3 public class LinkNode 4 { 5 public int data; 6 7 public LinkNode next; 8 } 9 10 private LinkNode head; 11 12 public void Add(int data) 13 { 14 if (head == null) 15 { 16 head = new LinkNode() { data = data }; 17 } 18 else

数据结构----顺序表与单链表(JAVA)

下面为学习顺序表和单链表的一些基本操作函数: 1 public class SeqList<T> extends Object { 2 protected int n; 3 protected Object[] element; 4 5 public SeqList(int length) { 6 this.element = new Object[length]; 7 this.n = 0; 8 } 9 10 public SeqList() { 11 this(64); 12 } 13 1

单链表反转C语言实现

单链表的反转可以使用循环,也可以使用递归的方式 1.循环反转单链表 循环的方法中,使用pre指向前一个结点,cur指向当前结点,每次把cur->next指向pre即可. 代码: # include <iostream> # include <cstdlib> using namespace std; struct linkNode { int val; linkNode *next; linkNode(int x):val(x),next(NULL){} }; linkNod

单链表反转python实现

单链表的反转可以使用循环,也可以使用递归的方式 1.循环反转单链表 循环的方法中,使用pre指向前一个结点,cur指向当前结点,每次把cur->next指向pre即可. 代码: class ListNode: def __init__(self,x): self.val=x; self.next=None; def nonrecurse(head): #循环的方法反转链表 if head is None or head.next is None: return head; pre=None; c

数据结构笔记5带头结点单链表

/* 本次操作是对带头节点单链表的操作  包括删除  插入 判空 建立  包括删除插入函数  显示函数 目的是为了对单链表做一个基本操作的总结----1*/ #include<stdio.h>#include<malloc.h>#include<conio.h>#define OK 1#define ERROR -1#define OVERFLOW -2#define ENDFLAG 0typedef struct LNode{ int data; struct LNo

小猪的数据结构辅助教程——2.2 线性表中的单链表

小猪的数据结构辅助教程--2.2 线性表中的单链表 标签(空格分隔): 数据结构 本节学习路线图与学习要点 学习要点: 1.理解顺序表以及单链表各自的有点以及缺点! 2.熟悉单链表的形式,对于头指针,头结点,尾结点,数据域和指针域这些名词要知道是什么! 3.熟悉单链表的结点结构 4.区分头指针与头结点! 5.熟悉创建单链表的两种方式:头插法和尾插法 6.了解单链表12个基本操作的逻辑 7.有趣的算法题:查找单链表的中间结点~ 1.单链表的引入(顺序表与单链表的PK) 2.单链表的结构图以及一些名