链表排序

下面的排序只针对无头结点的单链表,当然有头节点稍微改改就可以了

选择排序

选择排序就是每次选一个最小的,放到前面

为了方便操作,创造一个头结点

/**
 * Definition of singly-linked-list:
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *        this->val = val;
 *        this->next = NULL;
 *     }
 * }
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        //空链表或者只有一个节点
        if(head==nullptr||head->next==nullptr)return head;
        ListNode* temp=new ListNode(0);
        temp->next=head;
        for(ListNode* r=temp;r->next->next!=nullptr;r=r->next){
            ListNode* p,*q;
            //p用来存储最小的节点的前驱
            for(p=r,q=r->next;q->next!=nullptr;q=q->next){
                if(q->next->val<p->next->val){
                    p=q;
                }
            }
            q=p->next;//指向最小
            p->next=q->next;//断链
            
            //拼接
            q->next=r->next;
            r->next=q;
        }
        head=temp->next;
        delete temp;
        return head;
    }
};

插入排序

也创建一个头结点方便操作

插入排序由于链表不能往前迭代,所以只能在有序的部分遍历,找插入位置

所以这个不是真正意义上的插入排序

/**
 * Definition of singly-linked-list:
 * 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(head==nullptr||head->next==nullptr)return head;
        ListNode* temp=new ListNode(1);
        temp->next=head;
        //temp的链表现在是有序的那部分
        ListNode* p=head->next,*q,*r;
        head->next=nullptr;
        while(p){
            q=temp;
            //找插入位置
            while(q->next&&q->next->val<=p->val){
                q=q->next;
            }
            r=p->next;
            p->next=q->next;
            q->next=p;
            p=r;
        }
        return temp->next;
    }
};

快速排序

由于不能往前迭代,所以只能换种方法

p指向小于哨兵的最后一个,q是用来迭代的,如果q当前的值小于哨兵,就把他和p后面的交换,大概感觉就是下面这张图

 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void helper(ListNode* head,ListNode* tail){
        if(head==tail||head->next==tail)return;
        int val=head->val;
        ListNode* p=head;
        for(ListNode* q=head->next;q!=tail;q=q->next){
            if(q->val<val){
                p=p->next;
                if(p!=q){
                    swap(p->val,q->val);
                }
            }
        }
        swap(head->val,p->val);
        helper(head,p);
        helper(p->next,tail);
    }
    ListNode* sortList(ListNode* head) {
        if(head==nullptr||head->next==nullptr)return head;
        helper(head,nullptr);
        return head;
    }
};

归并排序

在链表排序中,归并应该算最快的

用快慢指针找中间,然后左边归并,右边归并,然后合并,都是基本操作

唯一要注意的是如果是空链表或者是只有一个节点,要直接返回,不然会死循环

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* merge(ListNode* p,ListNode* q){
        if(q==nullptr)return p;
        else if(p==nullptr)return q;
        ListNode* r,*tail=nullptr;
        while(p!=nullptr&&q!=nullptr){
            if(p->val<=q->val){
                if(tail!=nullptr){
                    tail->next=p;
                    tail=p;
                }
                else{
                    r=tail=p;
                }
                p=p->next;
            }
            else{
                if(tail!=nullptr){
                    tail->next=q;
                    tail=q;
                }
                else{
                    r=tail=q;
                }
                q=q->next;
            }
        }
        if(p==nullptr)p=q;
        tail->next=p;
        return r;
    }
    ListNode* sortList(ListNode* head) {
        if(head==nullptr||head->next==nullptr)return head;
        ListNode* slow=head,*fast=head;
        while(fast->next!=nullptr&&fast->next->next!=nullptr){
            slow=slow->next;
            fast=fast->next->next;
        }
        fast=slow->next;
        slow->next=nullptr;
        head=sortList(head);
        fast=sortList(fast);
        return merge(head,fast);
    }
};

总结

效率上,归并应该是最快的

在leetcode上,只有归并能过

https://leetcode.com/problems/sort-list/submissions/

下面这个是lintcode链表插入排序,用插入和选择都能过

https://www.lintcode.com/problem/insertion-sort-list/

下面这个是lintcode链表排序,快排和归并能过,目测选择和插入过不了

https://www.lintcode.com/problem/sort-list/description

下面这个是牛客网,虽然说是选择排序,但是只有归并能过

https://www.nowcoder.com/practice/f23604257af94d939848729b1a5cda08?tpId=188&&tqId=36717&rp=1&ru=/activity/oj&qru=/ta/job-code-high-week/question-ranking

 

C++完整版

#include<iostream>
#include<random>
#include<vector>
#include<algorithm>
using namespace std;
/**
 * 链表节点
 */
template<typename T>
class Node{
public:
    T data;
    Node<T>* next;
    Node():next(nullptr){}
    explicit Node(const T& data):data(data),next(nullptr){}
};
/**
 * 无头结点单链表
 */
template<typename T>
class LinkedList{
private:
    Node<T>* head;//链表
    /**
     * 两个链表归并
     * @param p 链表1
     * @param q 链表2
     * @return 归并后的链表
     */
    static Node<T>* merge(Node<T>* p,Node<T>* q){
        if(nullptr == p){
            return q;
        }
        else if(nullptr == q){
            return p;
        }
        Node<T>* r;//合并后的链表
        Node<T>* tail= nullptr;//合并后的链表的最后一个节点
        while(p!=nullptr&&q!=nullptr){
            if(p->data<=q->data){
                if (tail != nullptr) {
                    tail->next = p;
                    tail = p;
                }
                else {
                    r = tail = p;
                }
                p=p->next;
            }
            else{
                if (tail != nullptr) {
                    tail->next = q;
                    tail = q;
                }
                else {
                    r = tail = q;
                }
                q=q->next;
            }
        }
        if(p==nullptr){
            p=q;
        }
        tail->next=p;
        return r;
    }
    /**
     * 归并排序
     * @param head 链表
     * @return 排序后的链表
     */
    static Node<T>* mergeSort(Node<T>* head){
        //空链表或者只有一个元素
        if(head==nullptr||head->next==nullptr){
            return head;
        }
        //快慢指针,找中间节点
        Node<T>* fast=head,*slow=head;
        while(fast->next!=nullptr&&fast->next->next!=nullptr){
            slow=slow->next;
            fast=fast->next->next;
        }
        //右半边
        Node<T>* right=slow->next;
        //断链
        slow->next=nullptr;
        head=mergeSort(head);
        right=mergeSort(right);
        //归并
        return merge(head,right);
    }
    /**
     * 快排辅助函数
     * @param head 链表
     * @param tail 链表最后一个节点的下一个
     */
    static void quickSortHelper(Node<T>* head,Node<T>* tail){
        //空链表或者只有一个元素
        if(head==tail||head->next==tail){
            return;
        }
        Node<T>* p=head;//小于哨兵的节点的最后一个
        int val=head->data;//哨兵
        for(Node<T>* q=head->next;q!=tail;q=q->next){
            if(q->data<val){
                p=p->next;
                if(p!=q){
                    swap(p->data,q->data);
                }
            }
        }
        swap(head->data,p->data);
        quickSortHelper(head,p);
        quickSortHelper(p->next,tail);
    }
    /**
     * 快排
     * @param head 链表
     * @return 排序后的链表
     */
    static Node<T>* quickSort(Node<T>* head){
        //空链表或者只有一个元素
        if(head==nullptr||head->next==nullptr)return head;
        quickSortHelper(head,nullptr);
        return head;
    }
public:
    LinkedList():head(nullptr){}
    /**
     * 销毁链表
     */
    void destroy(){
        while(head!=nullptr){
            Node<T>* p=head->next;
            delete head;
            head=p;
        }
        head=nullptr;
    }
    ~LinkedList(){
        destroy();
    }
    void init(const vector<T>& init_data){
        destroy();
        Node<T>* tail= nullptr;
        for(const T& c:init_data){
            if(tail!=nullptr){
                tail->next=new Node<T>(c);
                tail=tail->next;
            }
            else{
                head=tail=new Node<T>(c);
            }
        }
    }
    explicit LinkedList(const vector<T>& init_data){
        head= nullptr;
        init(init_data);
    }
    /**
     * 判断链表是否有序
     * @return true是|false否
     */
    bool isSorted()const{
        if(head==nullptr||head->next==nullptr)return true;
        T pre=head->data;
        for(Node<T>* p=head->next;p!=nullptr;p=p->next){
            if(p->data<pre)return false;
            pre=p->data;
        }
        return true;
    }
    /**
     * 选择排序
     */
    void selectSort(){
        if(head==nullptr||head->next==nullptr){
            return;
        }
        auto temp=new Node<T>();
        temp->next=head;
        for(Node<T>* r=temp;r->next->next!=nullptr;r=r->next){
            Node<T>* p,*q;
            for(p=r,q=r->next;q->next!=nullptr;q=q->next){
                if(q->next->data<p->next->data){
                    p=q;
                }
            }
            q=p->next;
            p->next=q->next;
            q->next=r->next;
            r->next=q;
        }
        head=temp->next;
        delete temp;
    }
    /**
     * 插入排序
     */
    void insertSort(){
        if(head==nullptr||head->next==nullptr){
            return;
        }
        auto* temp=new Node<T>();//创建一个头结点
        temp->next=head;
        Node<T>* p=head->next;
        head->next=nullptr;
        while(p!=nullptr){
            Node<T>* q=temp;
            T val=p->data;
            while(q->next!=nullptr&&q->next->data<=val){
                q=q->next;
            }
            Node<T>* r=p->next;
            p->next=q->next;
            q->next=p;
            p=r;
        }
        head=temp->next;
        delete temp;
    }
    /**
     * 归并排序
     */
    void mergeSort(){
        head=mergeSort(head);
    }
    /**
     * 快速排序
     */
    void quickSort(){
        head=quickSort(head);
    }
    /**
     * 将链表转成vector
     * @return 转换后的vector
     */
    vector<T> getElements()const{
        vector<T> result;
        for(Node<T>* p=head;p!=nullptr;p=p->next){
            result.push_back(p->data);
        }
        return result;
    }
    friend ostream& operator<<(ostream& out,const LinkedList<T>& linkedList) {
        if(linkedList.head==nullptr){
            return out;
        }
        bool flag=false;
        for(Node<T>* p=linkedList.head;p!=nullptr;p=p->next){
            if(flag){
                out<<' ';
            }
            else{
                flag=true;
            }
            out<<p->data;
        }
        return out;
    }
};
bool isSame(vector<int>& a,vector<int>& b){
    if(a.size()!=b.size())return false;
    for(int i=0,size=a.size();i<size;++i){
        if(a[i]!=b[i])return false;
    }
    return true;
}
int main(){
    const int N=1000;
    random_device rd;
    vector<int> v;
    for(int i=0;i<N;++i){
        v.push_back(rd());
    }
    vector<int> temp=v;
    sort(v.begin(),v.end());
    vector<int> p;
    LinkedList<int> linkedList;
    bool flag=false;

    linkedList.init(temp);
    linkedList.selectSort();
    p=linkedList.getElements();
    if(!isSame(v,p)){
        cout<<"selectSort wrong"<<endl;
        flag=true;
    }

    linkedList.init(temp);
    linkedList.insertSort();
    p=linkedList.getElements();
    if(!isSame(v,p)){
        cout<<"insertSort wrong"<<endl;
        flag=true;
    }

    linkedList.init(temp);
    linkedList.mergeSort();
    p=linkedList.getElements();
    if(!isSame(v,p)){
        cout<<"mergeSort wrong"<<endl;
        flag=true;
    }

    linkedList.init(temp);
    linkedList.quickSort();
    p=linkedList.getElements();
    if(!isSame(v,p)){
        cout<<"quickSort wrong"<<endl;
        flag=true;
    }
    if(flag){
        for(int& c:temp){
            cout<<c<<' ';
        }
        cout<<endl;
    }
    else{
        cout<<"SUCCESS"<<endl;
    }

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nightmare004

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值