📜  排序 ak 排序双向链表(1)

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

排序双向链表

介绍

双向链表是一种常见的数据结构,它允许以任意方向遍历它的元素。排序双向链表则是在普通的双向链表的基础上,增加排序操作,使得链表中的元素按照一定的顺序排列。

算法

排序算法是实现排序双向链表的核心部分。下面介绍两种经典的排序算法:插入排序和归并排序。

插入排序

插入排序是一种简单有效的排序算法,其思想类似于打扑克牌。假设我们手中已经有一些牌,并按从小到大的顺序排列,现在要插入一张牌,我们从已有的牌的最右边开始,依次与手中的牌比较大小,直到找到合适的位置插入这张新牌。

在实现排序双向链表时,我们可以维护一个指向链表头的指针,从头开始遍历链表。对于每个节点,我们找到其应该插入的位置,并在该位置插入该节点。

插入排序的时间复杂度为O(n^2),其中n为链表长度。

归并排序

归并排序是一种基于分治思想的排序算法,其思想是将待排序序列不断地拆分成较小的子序列,直到每个子序列长度为1。然后将这些子序列按照大小顺序两两合并,直到最终合并成一个有序序列。

在实现排序双向链表时,我们可以先将整个链表拆分成两个大臣长度相等的子序列,然后递归地对这两个序列进行排序。在子序列排序完成之后,我们将它们按照顺序合并成一个更长的有序序列。

归并排序的时间复杂度为O(nlogn),其中n为链表长度。

代码实现
插入排序

下面是用C++实现的插入排序代码片段:

struct ListNode {
    int val;
    ListNode *next;
    ListNode *prev;
    ListNode(int x) : val(x), next(NULL), prev(NULL) {}
};

ListNode* insertionSortList(ListNode* head) {
    ListNode *dummy = new ListNode(0);
    dummy->next = head;
    ListNode *lastSorted = head, *curr = head->next;
    while (curr != NULL) {
        if (lastSorted->val <= curr->val) {
            lastSorted = lastSorted->next;
        } else {
            ListNode *prev = dummy;
            while (prev->next->val <= curr->val) {
                prev = prev->next;
            }
            lastSorted->next = curr->next;
            curr->next = prev->next;
            prev->next = curr;
        }
        curr = lastSorted->next;
    }
    return dummy->next;
}
归并排序

下面是用C++实现的归并排序代码片段:

ListNode* sortList(ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    }
    ListNode *slow = head, *fast = head->next;
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    ListNode *mid = slow->next;
    slow->next = NULL;
    ListNode *left = sortList(head);
    ListNode *right = sortList(mid);
    return merge(left, right);
}

ListNode* merge(ListNode* l1, ListNode* l2) {
    ListNode *dummy = new ListNode(0);
    ListNode *curr = dummy;
    while (l1 != NULL && l2 != NULL) {
        if (l1->val < l2->val) {
            curr->next = l1;
            l1 = l1->next;
        } else {
            curr->next = l2;
            l2 = l2->next;
        }
        curr = curr->next;
    }
    if (l1 != NULL) {
        curr->next = l1;
    } else {
        curr->next = l2;
    }
    return dummy->next;
}
总结

排序双向链表是一种高效的数据结构,在开发中有着广泛的应用。通过使用插入排序和归并排序等经典排序算法,我们可以轻松地对链表中的元素进行排序。在实际开发中,我们还可以根据具体需求进行定制化的排序算法实现,以满足业务需求。