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

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