给定一个单链表,请使用快速排序算法对其排序。
要求:期望平均时间复杂度为 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]<<' ';
}