單向鏈表節點包含結構體數組字段(如 `char id[12]`、`char name[20]`),需按指定字段(如 `id`)進行選擇排序,支持升序/降序。
typedef struct Student {
char id[12];
char name[20];
struct Student *next;
} Student;
Student *list_sort_asc(Student *head) {
Student *tail = head->next; // 當前有序區尾部
Student *curr;
Student tmp; // 臨時結構體用於交換
while (tail) {
curr = tail->next; // 掃描無序區
while (curr) {
// tail->id > curr->id 返回 >0,說明 curr 更小,需交換
if (strcmp(tail->id, curr->id) > 0) {
// 交換兩節點的所有數據字段
strcpy(tmp.id, tail->id);
strcpy(tmp.name, tail->name);
strcpy(tail->id, curr->id);
strcpy(tail->name, curr->name);
strcpy(curr->id, tmp.id);
strcpy(curr->name, tmp.name);
}
curr = curr->next;
}
tail = tail->next; // 有序區擴展
}
return head;
}
Student *list_sort_desc(Student *head) {
Student *tail = head->next;
Student *curr;
Student tmp;
while (tail) {
curr = tail->next;
while (curr) {
// tail->id < curr->id 返回 <0,說明 curr 更大,需交換
if (strcmp(tail->id, curr->id) < 0) {
strcpy(tmp.id, tail->id);
strcpy(tmp.name, tail->name);
strcpy(tail->id, curr->id);
strcpy(tail->name, curr->name);
strcpy(curr->id, tmp.id);
strcpy(curr->name, tmp.name);
}
curr = curr->next;
}
tail = tail->next;
}
return head;
}
初始: head → [1003] → [1001] → [1002] → NULL
↑tail
第1輪掃描無序區 [1001] [1002]:
發現 1001 < 1003 → 交換 tail(1003) 與 1001
發現 1002 < 1001 → 交換 tail(1001) 與 1002
結果: head → [1002] → [1003] → [1001] → NULL
↑tail
第2輪尾部後移,掃描 [1003] [1001]...
最終: head → [1001] → [1002] → [1003] → NULL (升序)
void print_list(Student *head) {
for (Student *p = head->next; p; p = p->next)
printf("[%s] %s\n", p->id, p->name);
}
// 分割鏈表為兩半(快慢指針)
Student *split(Student *head) {
Student *slow = head, *fast = head->next;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
Student *mid = slow->next;
slow->next = NULL;
return mid;
}
// 合併兩有序鏈表
Student *merge(Student *a, Student *b) {
Student dummy, *tail = &dummy;
while (a && b) {
if (strcmp(a->id, b->id) <= 0) { tail->next = a; a = a->next; }
else { tail->next = b; b = b->next; }
tail = tail->next;
}
tail->next = a ? a : b;
return dummy.next;
}
// 歸併排序入口
Student *merge_sort(Student *head) {
if (!head || !head->next) return head;
Student *mid = split(head);
head = merge_sort(head);
mid = merge_sort(mid);
return merge(head, mid);
}
本文實現了鏈表上基於結構體字符串字段的選擇排序(升序/降序),核心技巧是 `strcmp` 比較 + `strcpy` 交換數據域。對於生產環境大規模鏈表排序,強烈建議使用歸併排序(O(n log n)、穩定、僅指針操作),或構建指針數組間接排序。