O(nlogn)属于性能较优的排序算法,但是用在链表确实要注意很多,它不支持高效的随机访问,所以需要用在qsort这种,估计达不到O(logn) 这时突然想起来其实还是可以用
lumoto版的partition来qsort的,后面再试试看。堆排序几乎不可行,因为堆得调整不断的随机访问,链表效率极低,当时我只想到mergesort,
然后非递归版的太繁琐,我也不愿去看了,于是想可以非递归么,算了下时间复杂度,在mid=(low+high)/2这一步比之前加了O(n), 所以T(n)=2T(n/2)+2n, plug-in算出来是T(n)=n+2nlogn=O(nlogn)符合要求,于是开搞,就是要加个尾指针比较刮三,但是也还好。另外我觉得还是把copy放到Merge这一步结构比较清晰,改成其他要求的也比较容易。
里面就是算mid指针,比较纠结点,while(i<(length-1)/2) 还稍微倒腾了一下把奇偶统一起来,里面copy的时候我是直接copy到数组,然后再copy回linklist,这样不用在new新的堆空间了,提交挺顺利,直接AC了。
另外测试用了尾插法,也是始终记录尾指针,回来发现google几乎所有服务都不能用了,包括leetcode之前都gplus登陆的,换了host,改了实验协议也还是不行。。。。
于是只能蛋疼的重新注册一个账号。。。
代码:
#include <iostream>
using namespace std;
struct ListNode{
int val;
ListNode* next;
};
void Merge(ListNode* low, ListNode* mid, ListNode* high, int length);
ListNode* MergeSort(ListNode* low, ListNode* high);
ListNode *sortList(ListNode *head)
{
if(head==NULL||head->next==NULL) return head;
ListNode*p=head;
while(p->next!=NULL)
p=p->next;
return MergeSort(head,p);
}
ListNode* MergeSort(ListNode* low, ListNode* high)
{
if(low==high) return low;
else
{
//get length
int length=1;
ListNode* p=low;
while(p!=high)
{
length++;
p=p->next;
}
//get mid point
p=low;
int i=0;
while(i<(length-1)/2)
{
p=p->next;
i++;
}
//recursively merge two part
MergeSort(low,p);
MergeSort(p->next,high);
//merge two parts to one
Merge(low,p,high,length);
//Copy(low,a);
return low;
}
}
void Merge(ListNode* low, ListNode* mid, ListNode* high, int length)
{
ListNode* p1=low,*p2=mid->next;
int *a=new int[length];
int i=0;
while(p1!=mid->next&&p2!=high->next)
{
if(p1->val < p2->val)
{
a[i]=p1->val;
p1=p1->next;
}
else
{
a[i]=p2->val;
p2=p2->next;
}
i++;
}
if(p1==mid->next)
{
while(p2!=high->next)
{
a[i]=p2->val;
p2=p2->next;
i++;
}
}
else if(p2==high->next)
{
while(p1!=mid->next)
{
a[i]=p1->val;
p1=p1->next;
i++;
}
}
ListNode* q=low;
for(int i=0;i<length;i++)
{
q->val=a[i];
q=q->next;
}
delete []a;
}
ListNode* CreateLinkList(int* data, ListNode*& rail1, int n)
{
ListNode* head=NULL;
head=new ListNode();
head->val=data[0];
head->next=NULL;
ListNode* rail=head;// record each rail
for(int i=1;i<n;i++)
{
ListNode* p=new ListNode();
p->val=data[i];
p->next=NULL;
rail->next=p;
rail=rail->next;
}
rail1=rail;
return head;
}
void ShowList(ListNode* head)
{
while(head!=NULL)
{
cout<<head->val<<" ";
head=head->next;
}
cout<<endl;
return ;
}
int main()
{
int a[]={3,2,1,324,634,23};
ListNode* rail=NULL;
ListNode* head=CreateLinkList(a,rail,6);
ShowList(head);
//MergeSort(head,rail);
head=sortList(head);
ShowList(head);
return 0;
}