📅  最后修改于: 2023-12-03 15:40:53.741000             🧑  作者: Mango
该 C 程序用于对仅包含数字 0,1,2 的链表进行排序。程序流程使用快排思路的分治法,将链表中的数字分成三大类,根据数值大小分别归于 0,1,2。时间复杂度为 O(n)。
// 链表节点定义
struct ListNode {
int val;
struct ListNode *next;
};
// 新建链表节点
struct ListNode* createNode(int val) {
struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));
node -> val = val;
node -> next = NULL;
return node;
}
// 分治快排
struct ListNode* partition(struct ListNode* head, struct ListNode* end,
struct ListNode** newHead, struct ListNode** newEnd) {
struct ListNode* pivot = end; // pick the last node as pivot
struct ListNode *prev = NULL, *cur = head, *tail = pivot;
while (cur != pivot) {
if (cur -> val < pivot -> val) {
// Set new head if this is the first node that is less than pivot
if ((*newHead) == NULL) {
(*newHead) = cur;
}
prev = cur;
cur = cur -> next;
} else {
// Move current node to next of tail, and change tail
if (prev) {
prev -> next = cur -> next;
}
struct ListNode* tmp = cur -> next;
cur -> next = NULL;
tail -> next = cur;
tail = cur;
cur = tmp;
}
}
// Last node is also be placed in correct position
if ((*newHead) == NULL) {
(*newHead) = pivot;
}
(*newEnd) = tail;
return pivot;
}
struct ListNode* quickSort(struct ListNode* head, struct ListNode* end) {
if (!head || head == end) {
return head;
}
struct ListNode *newHead = NULL, *newEnd = NULL;
// Partition the linked list, and get pivot node
struct ListNode* pivot = partition(head, end, &newHead, &newEnd);
// If pivot is the smallest element - no need to recur for the left part.
if (newHead != pivot) {
struct ListNode* tmp = newHead;
while (tmp -> next != pivot) {
tmp = tmp -> next;
}
tmp -> next = NULL;
// Recur for the list before pivot
newHead = quickSort(newHead, tmp);
// Change next of last node of the left half to pivot
tmp = getTail(newHead);
tmp -> next = pivot;
}
// Recur for the list after the pivot element
pivot -> next = quickSort(pivot -> next, newEnd);
return newHead;
}
// 数字只有 0, 1, 2
struct ListNode* sortList(struct ListNode* head) {
if (!head || !(head -> next)) {
return head;
}
struct ListNode *tail = getTail(head);
return quickSort(head, tail);
}
void printList(struct ListNode* pList) {
while (pList != NULL) {
printf("%d ", pList -> val);
pList = pList -> next;
}
printf("\n");
}
int main() {
struct ListNode* head = createNode(2);
head -> next = createNode(1);
head -> next -> next = createNode(0);
head = sortList(head);
printList(head); // expect result: 0 1 2
return 0;
}
该程序使用快排思路的分治法对链表进行排序,算法时间复杂度为 O(n)。程序实现过程中,将链表节点的值分成三类,根据数值大小分别归于 0,1,2。