单链表快排----归并排序

给定一个单链表,请使用快速排序算法对其排序。

要求:期望平均时间复杂度为 O(nlogn)O(nlogn),期望额外空间复杂度为 O(logn)O(logn)。

思考题: 如果只能改变链表结构,不能修改每个节点的val值该如何做呢?

数据范围

链表中的所有数大小均在 intint 范围内,链表长度在 [0,10000][0,10000]。

输入样例:

[5, 3, 2]

输出样例:

[2, 3, 5]
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* quickSortList(ListNode* head) {
        if(head==NULL|| head->next==NULL) return head;//空链表或者只有一个节点,返回该链表
        
        quick_sort(head,nullptr);//nullptr 区分NULL和0 的区别
        return head;
    }
    void quick_sort(ListNode*st,ListNode*end)
    {
        if(st==end||st->next ==end) return ;//同上,注意end指的是链表最后一个节点的下一个节点
        
        ListNode*slow=st,*fast=st->next;//slow里面放的是小于开头节点的节点,fast放的是大于st节点的节点
        while(fast!=end)//遍历一遍该链表,把小于st的节点放到slow,大于的放到fast
        {
            if(st->val> fast->val)
            {
                slow=slow->next;
                swap(slow->val,fast->val);
            }
            fast=fast->next;
        }
        
        swap(st->val,slow->val);
        //递归调用,此时slow的数值是原来的begin的数值,正好和end为最后一个节点的下一个节点对应
        quick_sort(st,slow);
        quick_sort(slow->next,end);
        
    }
};

2、单链表归并排序

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* quickSortList(ListNode* head) {
        if(!head||!head->next) return head;//和快排同理
        
        ListNode*slow=head,*fast=head;//将链表划分为两部分,slow占用一半,fast占用一半
        
        while(fast->next&&fast->next->next)
        {
            fast=fast->next->next;
            slow=slow->next;
        }
        fast=slow->next;
        slow->next=nullptr;
//此时head一半单链表大小,fast一半链表大小
        return merge_sort(quickSortList(head),quickSortList(fast));
    }
    ListNode* merge_sort(ListNode*l1,ListNode*l2)//归并的过程,也就是回溯的过程
    {
      
        if(l1==nullptr) return l2;
        if(l2==nullptr) return l1;
        
        ListNode*p=new ListNode(0),*q=p;//q的目的是返回链表头结点,q->next为链表的头结点
        //归并排序的经典思路
        while(l1&&l2)
        {
            if(l1->val<l2->val) p->next=l1,l1=l1->next;
            else p->next=l2,l2=l2->next;
            
            p=p->next;
        }

        if(l1) p->next=l1;
        if(l2) p->next=l2;
        p=q->next;//返回头结点
        return p;
    }
};

3、快排模板

#include<iostream>

using namespace std;

int q[100010];

void sort(int l,int r,int q[])
{
    if(l>=r) return;
    
    int i=l-1,j=r+1,x=q[l+r>>1];
    while(i<j)
    {
        do i++; while(q[i]<x);
        
        do j--; while(q[j]>x);
        if(i<j)
        {
            swap(q[i],q[j]);
        }
        
    }
    sort(l,j,q);
    sort(j+1,r,q);
}

int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>q[i];
        
    }
    sort(0,n-1,q);
    for(int i=0;i<n;i++)
     cout<<q[i]<<' ';
}

4、经典归并排序模板

#include<iostream>

using namespace std;

int a[100010];
int n;
int tmp[100010];

void merge_sort(int a[],int l,int r)
{
    if(l>=r) return ;
    
    int mid=l+r>>1;
    merge_sort(a,l,mid);
    merge_sort(a,mid+1,r);
    int i=l,j=mid+1;
    int k=0;
    while(i<=mid&&j<=r)
    {
        if(a[i]<a[j])
        {
            tmp[k++]=a[i++];
            
        }
        else
        {
            tmp[k++]=a[j++];
        }
    }
    while(i<=mid)
    {
        tmp[k++]=a[i++];
    }
    while(j<=r) tmp[k++]=a[j++];
    
    for(int m=l,n=0;m<=r;m++,n++)
    {
        a[m]=tmp[n];
    }
    return;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];
    
    merge_sort(a,0,n-1);
    
    for(int i=0;i<n;i++) cout<<a[i]<<' ';
    
}

猜你喜欢

转载自blog.csdn.net/weixin_42333573/article/details/104858187