链表排序——单链表快排与归并

单链表有一个重要的特性,就是只能从前往后遍历。所以单链表的排序方法和普通的数组排序不一样。

一、快排

数组快排需要两个指针,一前一后往中间靠拢。由于单链表只能单向遍历,故需要设计不同的算法。

设定p和q指针,并且规定p和q之间的数都是大于pivot的数(包含p)。

1)p从start开始,也就是一开始p就是满足条件的p指针,q从p的下一个指针开始,也就是待判定的节点。

2)当q的数大于等于pivot(start),则该数可以在p和q之间,故只需要将q前进一位

3)如果q的数小于pivot则该节点应该在p之前。故将p前进一位,并且交换p q。

4)循环知道q == end

可以知道, p一直指向最后一个小于pivot的节点,故循环最后,交换p和start,就完成一次partion操作

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *pivot(ListNode *start, ListNode *end){
        ListNode *p = start, *q;
        q = p->next;
        while(q != end){
            if(q->val < start->val){
                p = p->next;
                int tmp = p->val;
                p->val = q->val;
                q->val = tmp;
            }
            q = q->next;
        }
        int tmp = p->val;
        p->val = start->val;
        start->val = tmp;
        return p;
    }
    void qc(ListNode *start, ListNode *end){
        if(start != end){
            ListNode *par = pivot(start, end);
            qc(start, par);
            qc(par->next, end);
        }
    }
    ListNode* sortList(ListNode* head) {
        qc(head, nullptr);
        return head;
    }
};

二、归并排序

归并排序要注意的地方是,怎么把两个有序的链表合并起来,一般采用傻逼节点方式。也就是设定一个傻逼节点,作为开始节点的前面一个节点。具体可以看代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:  
    ListNode* merge(ListNode *l1, ListNode *l2){
        ListNode idiot(0);
        ListNode *p = &idiot;
        while(l1 && l2){
            if(l1->val > l2->val){
                p->next = l2;
                l2 = l2->next;
            } else {
                p->next = l1;
                l1 = l1->next;
            }
            p = p->next;
        }
        p->next = l1 ? l1 : l2;
        return idiot.next;
    }
    ListNode* sortList(ListNode* head) {
        if(head == nullptr || head->next == nullptr)
            return head;
        ListNode *hare = head, *turtle = head;
        ListNode *turtle_shit = head;
        while(hare != nullptr && hare->next != nullptr){
            turtle_shit = turtle;
            turtle = turtle->next;
            hare = hare->next->next;
        }
        turtle_shit->next = nullptr;
        ListNode *l1 = sortList(head);
        ListNode *l2 = sortList(turtle);
        return merge(l1, l2);
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值