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

Posted 霜雪千年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归实现单链表的各种基本操作相关的知识,希望对你有一定的参考价值。

  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半天。。。~_~"||好好纪念一下。

以上是关于递归实现单链表的各种基本操作的主要内容,如果未能解决你的问题,请参考以下文章

单链表各种操作的代码实现

单链表就地逆置的两种方法(递归与普通循环)

单链表逆置

单链表的逆置使用递归算法出现-842150451这个值,请求高手予以解决。。

循环链表的建立及各种操作

单链表的逆置使用递归算法出现-842150451这个值,请求高手予以解决。。