链表排序

描述

给链表的结点进行排序。比如给出 1->3->2->0->null ,排序后 0->1->2->3->null。 这里介绍链表的插入排序和归并排序。

链表插入排序

插入排序就是已经前面 N1 个结点有序的情况下,将第 N 个结点分别跟前面的有序结点比较,使前N个结点仍然有序。跟数组的插入排序有所不同的是,数组是从后面开始比较,由于链表只能从前到后,所以链表插入排序是从前面依次开始比较。

最主要的思想是两个指针,一个指针指向已经排序好的链表,另外一个指向未排序的链表。每次比较,都要从头遍历已排序好的链表。

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * @param head: The first node of linked list.
     * @return: The head of linked list.
     */
    ListNode *insertionSortList(ListNode *head) {
        // write your code here
        if(NULL == head)
            return head;
        ListNode *pNext, *prev, *curNode, *q;
        //head指向已经排序好的链表,pNext指向未排序的链表。实际是都是同一个链表
        pNext = head->next;
        head->next = NULL;

        while(pNext != NULL)
        {
            curNode = pNext;
            pNext = pNext->next;
            int val = curNode->val;
            //关键是这个for循环。如果当前未排序的结点大于已排序好的,继续往下比较,并保存已排序好的结点,方便后序插入。如果小于,则退出for循环
            for(prev = NULL, q = head; q && q->val <= val; prev = q, q = q->next );
            //比头节点小
            if(q == head)
            {
                head = curNode;
            }

            else
            {
                prev->next = curNode;
            }
            //插入操作
            curNode->next = q;
        }

        return head;
    }
};

链表归并排序

在数组的归并排序中,归并排序需要 O(n) 的额外空间, 而链表因为排序只是指针的变化,只需要常数级的空间,将链表拆分成两半,然后合并两个子链表。

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * @param head: The first node of linked list.
     * @return: You should return the head of the sorted linked list,
                    using constant space complexity.
     */
    ListNode *sortList(ListNode *head) {
        // write your code here
        if(NULL == head)
            return NULL;
        int ListLen = 0;

        ListNode *pNode = head;

        while(pNode != NULL)
        {
            ListLen ++;
            pNode = pNode->next;
        }

        return sortList_core(head, ListLen);
    }

private:

    ListNode *sortList_core(ListNode *head, int ListLen)
    {
        if(NULL == head || ListLen <= 0)
            return head;

        int mid = ListLen / 2;
        ListNode *midList = head;

        int count = 1;

        while(count < mid)
        {
            midList = midList->next;
            count ++;
        }

        ListNode *rList = sortList_core(midList->next, ListLen - mid);
        midList->next = NULL;
        ListNode *lList = sortList_core(head, mid);

        return Merge2List(lList, rList);
    }

    ListNode *Merge2List(ListNode *L1, ListNode *L2)
    {
        ListNode *dummy = new ListNode(0);
        ListNode *lastNode = dummy;
        while((L1 != NULL) && (L2 != NULL))
        {
            if(L1->val < L2->val)
            {
                lastNode->next = L1;
                L1 = L1->next;
            }

            else
            {
                lastNode->next = L2;
                L2 = L2->next;
            }

            lastNode = lastNode->next;
        }

        lastNode->next = (NULL != L1)? L1 : L2;

        return dummy->next;
    }
};



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值