链表归并排序

对一个链表进行排序,且时间复杂度为O(nlongn),空间复杂度为常量。
首先一看到O(nlongn)的排序就应该想到归并排序和快速排序。

归并排序:
在一般情况下,归并排序的空间复杂度为O(n)的,需要复制出相等空间来进行赋值排序。但实际上,对于链表是可以实现常数空间的。

利用归并排序的思想递归的将当前链表分为两段,然后merge,分两段的方法:

使用fast-slow法,用两个指针,一个每次走一步,另一个每次走两步,之道走到末尾,慢指针指向的就是中间位置。这样就分成了两段。

快速排序:
当然,这里也可以用快速排序,但是由于快速排序它的元素交换次数太多了就可能会影响时间效率。所以这里适合采用归并排序。

/**********************************************************
 * Author        : oyjb
 * Email         : jbouyang@126.com
 * Last modified : 2015-06-25 13:51
 * Filename      : sortList.cpp
 * Description   : 
 * *******************************************************/
/**Definition of ListNode.*/
 struct ListNode
 {
     int val;
     ListNode *next;
     ListNode(int x) : val(x),next(NULL);
 };
  
class Solution
{  
public:
    ListNode *sortList(ListNode *head)
    {
        if (!head || !head->next)//头结点为空或者只有一个结点
            return head;
        return mergeSort(head);
    }
 
    ListNode* mergeSort(ListNode *head)
    {
        if (!head || !head->next)
            return head;
        ListNode *p = head,*q = head,*pre = NULL;
        /*
         * 找到链表中间节点
         * 让p每次走一步,q每次走两步
         * 并且记录p的前驱节点
         */
        while (q && q->next != NULL)
        {
            q = q->next->next;
            pre = p;//记录p的前躯
            p = p->next;
        }
 
        pre->next = NULL;//从p节点处断开
        //recusive
        ListNode *lhalf = mergeSort(head);
        ListNode *rhalf = mergeSort(p);
 
        return merge(lhalf,rhalf);
    }
 
    ListNode* merge(ListNode *lh,ListNode *rh)
    {
        ListNode *temp = new ListNode(0);
        ListNode *p = temp;
        while (lh != NULL && rh != NULL)
        {
            if (lh->val <= rh->val)
            {
                p->next = lh;
                lh = lh->next;
            }
            else
            {
                p->next = rh;
                rh = rh->next;
            }
            p = p->next;
        }
        if (!lh) //如果左链表为空,则添加右链表到尾部,反之
            p->next = rh;
        else
            p->next = lh;
        p = temp->next;
        temp->next = NULL;
        delete temp;
        return p;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值