为链表排序量身定做的算法--归并排序

Posted C_YCBX Py_YYDS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为链表排序量身定做的算法--归并排序相关的知识,希望对你有一定的参考价值。

为什么说为链表排序量身定做?

很简单,如果归并排序用在数组中,是需要额外的数组作为辅助,而如果是链表,这个操作就很简单了,每次去结点直接拿下来即可,没必要畏畏缩缩,所以空间上不存在额外的使用。
看看效率:在这里插入图片描述

如何实现?

归并排序三步走

  1. 自顶向下分割链表,直到单个有序。(merge函数实现)
  2. 合并两个有序链表(mergeTwoLists函数实现)
  3. 根据递归特性LIFO,将分割后的单个有序结点利用mergeTwoLists排序,自底向上返回得到最终的结果。

对链表来说,难就难在分割,我们利用快慢指针寻找中点来分割。

具体代码:

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        //剔除不需排序的特殊情况
        if(!head||!head->next)
            return head;
        //注意是左闭右开区间[head,nullptr)
       return merge(head,nullptr);
    }
private:
    ListNode* merge(ListNode* head,ListNode* tail){
        //由于是左闭右开,所以当左端点的下一个元素等于右端点,则当前区间只含有一个结点
        if (head->next == tail) {
            head->next = nullptr;
            return head;
        }
        //用快慢指针得到中间节点(fast走两步,slow走一步,当fast走到尾部则slow在中间)
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast!=tail&&fast->next!=tail){
            fast = fast->next->next;
            slow = slow->next;
        }
        //不断的分治,由于递归LIFO特性,会分解到单个结点才罢休,此时单个是有序的故可以mergeTwoLists排
        //分治区间为[head,slow)U[slow,tail)
        return mergeTwoLists(merge(head,slow),merge(slow,tail));
    }
    //合并两个有序链表的函数
  ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* head;
        if(!l1)return l2;
        if(!l2)return l1;
        if(l1->val<l2->val){
            l1->next = mergeTwoLists(l1->next,l2);
            head = l1;
        }else{
            l2->next = mergeTwoLists(l1,l2->next);
            head = l2;
        }
        return head;
    }
};

以上是关于为链表排序量身定做的算法--归并排序的主要内容,如果未能解决你的问题,请参考以下文章

链表归并排序

算法链表的快速排序和归并排序

算法链表的快速排序和归并排序

链表排序(冒泡选择插入快排归并希尔堆排序)

链表的快速排序和归并排序

排序算法之归并排序