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