進擊的小白Day013——通訊錄(三)
阿新 • • 發佈:2018-12-22
今天重新把通訊錄的程式完善了一下,可以完結了,通訊錄這種程式真的很適合來訓練結構體、指標和連結串列方面的知識。
貼程式碼:
#include <stdio.h> #include <stdlib.h> #include <malloc.h> #define MAX 100 /*建立結構體連結串列,固定結構,背下來*/ typedef struct people { char name[MAX]; char sex[MAX]; int age; long long int tel; char addr[MAX]; struct people *pNext; }Node, *pNode; /*Node為結構體變數,pNode為結構體指標變數,也可以只寫Node,在定義指標的時候寫成(Node *p)*/ /*定義全域性變數,記錄最後錄入的聯絡人的節點數*/ int num = 0; int main(void) { int flag; char ch; pNode pHead = NULL; /*首次定義頭指標需要置零*/ pNode CreatList(void); pNode CreatMember(pNode); void DeleteMember(pNode); void DeleteList(pNode); void FindMember(pNode); void ModifyMember(pNode); void TraverseList(pNode); void DeleteAll(pNode); void SortList(pNode); while (1) { printf("1.新增聯絡人資訊\n2.刪除指定聯絡人資訊\n3.查詢指定聯絡人資訊\n4.修改指定聯絡人資訊\n5.顯示所有聯絡人資訊\n6.清空所有聯絡人\n7.以名字排序所有聯絡人\n"); printf("請輸入要進行的操作:"); scanf_s("%d", &flag); printf("\n"); while (getchar() != '\n') { ch = getchar(); } switch (flag) { case 1: { /*首次錄入聯絡人*/ if (num == 0) { pHead = CreatList(); } /*重複錄入聯絡人*/ else { pHead = CreatMember(pHead); } printf("\n"); break; } case 2: { /*剩餘聯絡人超過1人時,令連結串列為空表*/ if (num == 1) { DeleteList(pHead); } /*正常刪除*/ else { DeleteMember(pHead); } printf("\n"); break; } case 3: { FindMember(pHead); printf("\n"); break; } case 4: { ModifyMember(pHead); printf("\n"); break; } case 5: { /*連結串列中有聯絡人時,正常遍歷*/ if (num > 0) { TraverseList(pHead); } /*空連結串列*/ else { printf("無聯絡人。"); } printf("\n"); break; } case 6: { DeleteAll(pHead); printf("\n"); break; } case 7: { SortList(pHead); printf("\n"); break; } } printf("現有%d個聯絡人。\n\n\n", num); } return 0; } /*首次錄入聯絡人,建立一個新的連結串列*/ pNode CreatList(void) { /*定義頭節點、尾節點、新節點*/ pNode pHead, pTail, pNew; pHead = (pNode)malloc(sizeof(Node)); /*為頭指標開闢一塊記憶體*/ pTail = pHead; /*空連結串列的頭節點就是尾節點*/ pTail->pNext = NULL; /*尾節點指向空值*/ /*輸入資料給新節點*/ pNew = (pNode)malloc(sizeof(Node)); /*為新節點開闢記憶體*/ printf("請輸入聯絡人姓名:"); scanf_s("%s", &pNew->name, MAX); printf("請輸入聯絡人性別:"); scanf_s("%s", &pNew->sex, MAX); printf("請輸入聯絡人年齡:"); scanf_s("%d", &pNew->age); printf("請輸入聯絡人電話:"); scanf_s("%lld", &pNew->tel); printf("請輸入聯絡人地址:"); scanf_s("%s", &pNew->addr, MAX); /*新節點接入連結串列*/ pTail->pNext = pNew; /*令原來的尾節點指向新節點*/ pNew->pNext = NULL; /*新節點指向空值*/ pTail = pNew; /*新節點成為新的尾節點,原來的尾節點成為中間節點*/ /*錄入聯絡人+1*/ num++; return pHead; } /*重複錄入聯絡人,將新的聯絡人接到原有的連結串列中*/ pNode CreatMember(pNode p) { /*定義新連結串列的頭節點、尾節點、新節點、臨時節點*/ pNode pHead, pTail, pNew, pSwap, pRepeat; char a[MAX]; pHead = p; /*將原有的連結串列賦給pHead*/ pRepeat = p->pNext; /*尋找原有連結串列的最後一個節點*/ pSwap = NULL; /*定義一個pVal來臨時儲存最後一個節點的資料*/ while (p != NULL) { pSwap = p; /*pVal始終為p的前一個節點,當遍歷結束時,p為空,pVal即為最後一個節點*/ p = p->pNext; } pTail = pSwap; /*令pTail成為連結串列最後一個節點*/ pTail->pNext = NULL; /*尾節點指向空值*/ /*輸入資料給新節點*/ pNew = (pNode)malloc(sizeof(Node)); printf("請輸入聯絡人姓名:"); scanf_s("%s", &pNew->name, MAX); printf("請輸入聯絡人性別:"); scanf_s("%s", &pNew->sex, MAX); printf("請輸入聯絡人年齡:"); scanf_s("%d", &pNew->age); printf("請輸入聯絡人電話:"); scanf_s("%lld", &pNew->tel); printf("請輸入聯絡人地址:"); scanf_s("%s", &pNew->addr, MAX); /*判斷新錄入的聯絡人是否已存在*/ while (pRepeat != NULL) { if (strcmp(pNew->name, pRepeat->name) == 0) { printf("聯絡人已存在!\n"); return pHead; } pRepeat = pRepeat->pNext; } /*新節點接入連結串列*/ pTail->pNext = pNew; /*令原來的尾節點指向新節點*/ pNew->pNext = NULL; /*新節點指向空值*/ pTail = pNew; /*新節點成為新的尾節點,原來的尾節點成為中間節點*/ /*錄入聯絡人+1*/ num++; return pHead; } /*刪除第一個聯絡人,令連結串列為空*/ void DeleteList(pNode p) { /*定義臨時節點*/ pNode pSwap; char a[MAX]; printf("請輸入要刪除的聯絡人姓名:"); pSwap = p; /*將聯絡人鏈表頭節點賦值給臨時節點*/ scanf_s("%s", a, MAX); if (strcmp(pSwap->pNext->name, a) == 0) /*檢查姓名是否匹配*/ { pSwap = NULL; /*刪除聯絡人-1*/ num--; } else { printf("聯絡人不存在!"); } } /*刪除指定聯絡人*/ void DeleteMember(pNode p) { /*定義臨時節點*/ pNode pSwap, pVal; char a[MAX]; printf("請輸入要刪除的聯絡人姓名:"); pSwap = p; /*將聯絡人鏈表頭節點賦值給臨時節點*/ pVal = p; scanf_s("%s", a, MAX); /*遍歷*/ while (pSwap != NULL) { if (strcmp(pSwap->name, a) == 0) /*檢查姓名是否匹配*/ { pVal->pNext = pVal->pNext->pNext; break; } pVal = pSwap; /*儲存要刪除的節點的前一節點*/ pSwap = pSwap->pNext; } if (pSwap == NULL) { printf("未找到聯絡人!\n"); } /*刪除聯絡人-1*/ num--; } /*查詢聯絡人*/ void FindMember(pNode p) { /*定義臨時節點*/ pNode pSwap; char a[MAX]; printf("請輸入要查詢的聯絡人姓名:"); scanf_s("%s", a, MAX); pSwap = p->pNext; /*將聯絡人鏈表頭節點賦值給臨時節點*/ /*遍歷*/ while (pSwap != NULL) { if (strcmp(pSwap->name, a) == 0) /*檢查姓名是否*/ { printf("%s ", pSwap->name); printf("%s ", pSwap->sex); printf("%d ", pSwap->age); printf("%lld ", pSwap->tel); printf("%s\n", pSwap->addr); break; } pSwap = pSwap->pNext; } if (pSwap == NULL) { printf("未找到聯絡人!\n"); } } /*修改聯絡人*/ void ModifyMember(pNode p) { /*定義臨時節點*/ pNode pSwap; char a[MAX]; printf("請輸入要查詢的聯絡人姓名:"); scanf_s("%s", a, MAX); pSwap = p->pNext; /*將聯絡人鏈表頭節點賦值給臨時節點*/ /*遍歷*/ while (pSwap != NULL) { if (strcmp(pSwap->name, a) == 0) /*檢查姓名是否*/ { /*輸入資料給新節點*/ printf("請輸入聯絡人姓名:"); scanf_s("%s", &pSwap->name, MAX); printf("請輸入聯絡人性別:"); scanf_s("%s", &pSwap->sex, MAX); printf("請輸入聯絡人年齡:"); scanf_s("%d", &pSwap->age); printf("請輸入聯絡人電話:"); scanf_s("%lld", &pSwap->tel); printf("請輸入聯絡人地址:"); scanf_s("%s", &pSwap->addr, MAX); break; } pSwap = pSwap->pNext; } if (pSwap == NULL) { printf("未找到聯絡人!\n"); } } /*遍歷輸出所有聯絡人*/ void TraverseList(pNode pHead) { /*定義臨時節點*/ pNode p; p = pHead->pNext; /*把pHead->pNext而不是pHead賦給p,是因為pHead的資料域本身沒有意義,因此只需要賦值pHead->pNext,即將第一個節點的資料域和指標域賦給p*/ /*執行遍歷*/ while (p != NULL) { printf("%s ", p->name); printf("%s ", p->sex); printf("%d ", p->age); printf("%lld ", p->tel); printf("%s\n", p->addr); p = p->pNext; } } /*刪除第一個聯絡人,令連結串列為空*/ void DeleteAll(pNode p) { /*定義臨時節點*/ pNode pSwap; /*連結串列清空*/ pSwap = p; /*將聯絡人鏈表頭節點賦值給臨時節點*/ pSwap = NULL; /*聯絡人數量歸零*/ num = 0; } /*排序*/ void SortList(pNode pp) { /*定義臨時節點*/ pNode p, q; int i, j, m = num; /*進行num-1輪氣泡排序*/ for (i = 0; i < num - 1; i++) { /*頭指標重置*/ p = pp; q = pp->pNext; /*單論氣泡排序,將最大的數送到最下面*/ for (j = 0; j < m - 1; j++) { if (q->name[0] > q->pNext->name[0]) { p->pNext = q->pNext; q->pNext = q->pNext->pNext; p->pNext->pNext = q; q = p->pNext; } q = q->pNext; p = p->pNext; } m--; } }
在這邊寫一個完整的連結串列氣泡排序單步教程吧,免得以後忘記了。
首先說一下,關於“p->next = q->next”語句的理解:
① “p->next”看作一個過程,是個動詞,理解為“p的下一個節點是XX”;
② “q->next”看作一個整體,是個名詞,代表一個節點,理解為“p的下一個節點”。