📌  相关文章
📜  用于对 0、1 和 2 的链表进行排序的 C 程序(1)

📅  最后修改于: 2023-12-03 15:40:53.741000             🧑  作者: Mango

用于对 0、1 和 2 的链表进行排序的 C 程序

简介:

该 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。