期末課程設計將C語言難度大幅提升,首次接觸分層架構(View/Service/Persistence),這一切的基礎都建立在鏈表操作之上。本文整理自《C語言程序設計教程》第十章,系統梳理鏈表核心操作,並附完整可運行代碼。
鏈表 vs 數組:
malloc 動態分配,用指針串聯,物理可不連續。每個結點包含數據域和指針域(指向下一結點),末結點指針為 NULL。結構體定義:
struct Student {
char cName[20];
int iNumber;
struct Student *next; // 指向本結構體類型的指針
};
malloc 結點,靈活無上限,工程首選。單鏈表只有 next 指針,單向鏈接。採用尾插法創建:
struct Student *Create() {
struct Student *pHead = NULL, *pEnd, *pNew;
iCount = 0;
pEnd = pNew = (struct Student *)malloc(sizeof(struct Student));
scanf("%s%d", pNew->cName, &pNew->iNumber); // 讀首結點
while (pNew->iNumber != 0) { // 學號為0結束
iCount++;
if (iCount == 1) {
pNew->next = pHead;
pEnd = pHead = pNew;
} else {
pNew->next = NULL;
pEnd->next = pNew;
pEnd = pNew;
}
pNew = (struct Student *)malloc(sizeof(struct Student));
scanf("%s%d", pNew->cName, &pNew->iNumber);
}
free(pNew); // 釋放最後多分配的結點
return pHead;
}
遍歷輸出:
void print(struct Student *pHead) {
struct Student *pTemp = pHead;
int i = 1;
printf("總共%d個學生:\n", iCount);
while (pTemp != NULL) {
printf("第%d個:姓名%s 學號%d\n", i++, pTemp->cName, pTemp->iNumber);
pTemp = pTemp->next;
}
}
struct Student *Insert(struct Student *pHead, int number) {
struct Student *p = pHead, *pNew;
while (p && p->iNumber != number) p = p->next; // 定位
pNew = (struct Student *)malloc(sizeof(struct Student));
scanf("%s%d", pNew->cName, &pNew->iNumber);
pNew->next = p->next;
p->next = pNew;
iCount++;
return pHead;
}
void Delete(struct Student *pHead, int number) {
struct Student *pTemp = pHead, *pPre = pTemp;
for (int i = 0; i < number; i++) {
pPre = pTemp;
pTemp = pTemp->next;
}
pPre->next = pTemp->next; // 斷鏈
free(pTemp); // 釋放內存
iCount--;
}
雙向鏈表每結點有 llink(前驅)和 rlink(後繼)兩個指針,可雙向遍歷。結構:
typedef struct Node {
char name[20];
struct Node *llink, *rlink;
} STUD;
h 不存數據)STUD *creat(int n) {
STUD *h = (STUD *)malloc(sizeof(STUD));
h->name[0] = '\0'; h->llink = NULL; h->rlink = NULL;
STUD *p = h, *s;
for (int i = 0; i < n; i++) {
s = (STUD *)malloc(sizeof(STUD));
printf("輸入第%d個姓名:", i+1);
scanf("%s", s->name);
p->rlink = s; s->llink = p; s->rlink = NULL;
p = s;
}
h->llink = p; p->rlink = h; // 首尾相連成環
return h;
}
void print(STUD *h) {
STUD *p = h->rlink;
while (p != h) { printf("%s ", p->name); p = p->rlink; }
printf("\n");
}
STUD *search(STUD *h, char *x) {
STUD *p = h->rlink;
while (p != h) {
if (strcmp(p->name, x) == 0) return p;
p = p->rlink;
}
printf("未找到!\n");
return NULL;
}
next == head。無需專門頭結點。a/b/c 分別跟蹤兩鏈表當前結點與合併鏈表尾部,類似歸併排序合併步驟,時間複雜度 O(m+n)。void merge(struct stud *La, struct stud *Lb) {
struct stud *a = La->next, *b = Lb->next, *c = La;
while (a && b) {
if (a->num <= b->num) { c->next = a; c = a; a = a->next; }
else { c->next = b; c = b; b = b->next; }
}
c->next = a ? a : b;
free(Lb); // 釋放Lb頭結點
}
雙向鏈表增加一個指針域即可指向前驅;同理,再加 ulink/dlink 可構建二維鏈表(邏輯上),物理內存仍線性。三維、更高維同理可擴展,待數據結構課程深入探索。
鏈表是C語言指針運用的集大成者。掌握結構體定義、malloc/free 內存管理、指針斷鏈與重鏈(插入/刪除核心)、遍歷邏輯,單向→雙向→循環層層遞進,再結合文件持久化,即可構建完整的數據管理系統(如影片信息管理系統)。代碼規範、邊界檢查(空指針、越界)是工程化關鍵。