20170514_对单链表排序

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函数,实现上述步骤。 


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值