20170514_对单链表排序
归并排序算法
//148. Sort List
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
#include<iostream>
#include<vector>
using namespace std;
//单链表节点
struct ListNode
{
int val;
ListNode *next;
ListNode(int x):val(x),next(NULL) {}
};
//尾插法建立一个单链表
ListNode *CreatList(ListNode * &root, vector<int> &a)
{
int n=a.size();
if(n==0)
return root;
else
{
root=new ListNode(a[0]);
ListNode *r=root;
for(int i=1; i<n; ++i)
{
ListNode *s=new ListNode(a[i]);
r->next=s;
r=s;
}
return root;
}
}
//顺序输出一个单链表
void OutList(ListNode *root)
{
ListNode *p=root;
while(p!=NULL)
{
if(p->next!=NULL)
cout<<p->val<<",";
else
cout<<p->val;
p=p->next;
}
cout<<endl;
}
//单链表逆置
ListNode *ConvertList(ListNode *root)
{
if(root==NULL || root->next==NULL)
return root;
else
{
ListNode *pcur=root;
ListNode *qnext=pcur->next;
pcur->next=NULL;
while(qnext!=NULL)
{
root=qnext;
ListNode *qq=qnext->next;
qnext->next=pcur;
pcur=qnext;
qnext=qq;
}
return root;
}
}
//Sort a linked list in O(n log n) time using constant space complexity.
class Solution
{
public:
//3、归并排序
ListNode *sortList(ListNode *head)
{
if (!head || !head->next)
return head;
return mergesort(head);
}
//2、一趟归并排序
ListNode *mergesort(ListNode *head)
{
if (head == NULL || head->next == NULL) //节点为空或者就一个节点了,直接返回
return head;
ListNode *fast=head; //快慢指针的应用!
ListNode *slow=head;
while(fast->next != NULL && fast->next->next != NULL) //后续至少还有两个节点,则一共三个节点,再继续分割;
{ //否则,就意味着就剩两个节点了,直接可以排序了。
fast=fast->next->next; //快指针每次走两步
slow=slow->next; // 慢指针每次走一步
} //故:快指针到结尾处时,慢指针正好在中间位置。
ListNode *head2=slow->next; //右侧的新序列的第一个节点
slow->next=NULL; //截断左侧序列
ListNode *head1=head; //左侧的新序列的第一个节点
head1=mergesort(head1); //递归地对左半部分进行归并排序
head2=mergesort(head2); //递归地对右半部分进行归并排序
return merge(head1,head2); //head1 和 head2 已经是有序的了!
}
//1、对已经有序的两个单链表进行 一次归并
ListNode *merge(ListNode *h1, ListNode *h2)
{
ListNode *temp=new ListNode(0);
ListNode *p=temp;
while(h1 && h2) //对两个单链表进行合并
{
if(h1->val <= h2->val)
{
p->next=h1;
h1=h1->next;
}
else
{
p->next=h2;
h2=h2->next;
}
p=p->next;
}
if (h1!=NULL)
p->next=h1;
if (h2!=NULL)
p->next=h2;
p=temp->next;
temp->next=NULL;
delete temp;
return p;
}
};
int main()
{
vector<int> a;
int ch;
cout<<"依次输入单链表节点数据:"<<endl;
while(cin>>ch)
a.push_back(ch);
ListNode *r;
ListNode *root=CreatList(r,a);
cout<<"单链表建立完成."<<endl;
cout<<"顺序输出单链表:"<<endl;
OutList(root);
cout<<"顺序输出单链表完成."<<endl;
//cout<<"逆置该单链表:"<<endl;
//ListNode *root2=ConvertList(root);
//cout<<"输出逆置后的单链表:"<<endl;
//OutList(root2);
//cout<<"逆置后的单链表输出完成."<<endl;
Solution example;
root=example.sortList(root);
OutList(root);
system("pause");
return 0;
}
// 思路:
//因为题目要求复杂度为O(nlogn),故可以考虑归并排序的思想。
//归并排序的一般步骤为:
//1)将待排序数组(链表)取中点并一分为二;
//2)递归地对左半部分进行归并排序;
//3)递归地对右半部分进行归并排序;
//4)将两个半部分进行合并(merge),得到结果。
//
//所以对应此题目,可以划分为三个小问题:
//1)找到链表中点 (快慢指针思路,快指针一次走两步,慢指针一次走一步,快指针在链表末尾时,慢指针恰好在链表中点);
//2)写出merge函数,即如何合并链表。 (见merge-two-sorted-lists 一题解析)
//3)写出mergesort函数,实现上述步骤。