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 << "******************************************************************************\n"; 215 cout << " 1. 建立空鏈表(不帶頭節點); 2. 輸入指定個數的數據元素創建鏈表\n"; 216 cout << " 3. 正序打印表中元素 ; 4. 逆序打印表中元素\n"; 217 cout << " 5. 求表中元素的最大值; 6. 求表中元素的最小值\n"; 218 cout << " 7. 返回單鏈表的長度; 8. 遞歸求該表中所有節點元素的和\n"; 219 cout << " 9. 查找某元素的前驅元素; 10.判斷單鏈表是否遞增有序 \n"; 220 cout << " 11.在單鏈表的第i個位置插入元素e 12.打印單鏈表中從某節點元素開始后的所有節點\n"; 221 cout << " 13.刪除單鏈表的第i個元素 14.求表所有元素的平均值 \n"; 222 cout << " 0. 退出\n"; 223 cout << "*******************************************************************************\n"; 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) << "。\n" << endl; 269 } 270 else 271 cout << "當前為空鏈表" << endl << endl; 272 break; 273 case 6: //求表中元素的最小值 274 if (count_LNode(L)){ 275 cout << "表中最小的元素為:" << minVal_List(L) << "。\n" << endl; 276 } 277 else 278 cout << "當前為空鏈表" << endl << endl; 279 break; 280 case 7: //返回單鏈表的長度 281 if (count_LNode(L)) 282 cout << "當前單鏈表表長為" << count_LNode(L) << "。\n" << endl; 283 else 284 cout << "當前為空表" << endl << endl; 285 break; 286 case 8: //遞歸求該表中所有元素的和 287 if (count_LNode(L)) 288 cout << "當前表中所有元素的和為" << getSum_List(L) << "。\n" << 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 << "。\n" << 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 << "。\n" << 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 << "。\n" << 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 }