Sort List

Sort a linked list in O(n log n) time using constant space complexity.

此题要求时间复杂度为O(nlgn)第一印象即用快速排序和归并排序,由于快速排序的不稳定,跨度大,故我决定采用归并排序。网上我记得有看过使用快排的!


#include <iostream.h>
#include <string.h>

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};


void printlist(ListNode *head)
{
	while(head!=NULL)
	{
		cout << head->val << " ";
        head = head->next;
	}
}

void debug_disp(ListNode *head,char *str)
{
	cout<<endl<<str;
	printlist(head);
	
}

ListNode *get_midpos(ListNode *head,ListNode *end) {
	
	ListNode *mid_pos,*pre_pos;
	ListNode *end_pos;
	
	//if(head == NULL||head->next==NULL)return head;
	
	mid_pos=head;
	end_pos=head;
	
	while(end_pos != end&&end_pos->next != end)
	{
		pre_pos=mid_pos;
		mid_pos=mid_pos->next;
		
		end_pos=end_pos->next->next;
	}
	return pre_pos;
}

ListNode *merge(ListNode *first_lk,ListNode *second_lk) { 
	
	ListNode head_temp(0);
	ListNode* temp_head = &head_temp; 

	ListNode *save_head=temp_head;
	ListNode* head ;

	debug_disp(first_lk,"merge_list1:");
	debug_disp(second_lk,"merge_list2:");

	while(first_lk!=NULL&&second_lk!=NULL)
	{
		if(first_lk->val<second_lk->val)
		{
			temp_head->next=first_lk;
			first_lk=first_lk->next;
		}
		else
		{
			temp_head->next=second_lk;
			second_lk=second_lk->next;	
		}
		temp_head=temp_head->next;
	}
	if(first_lk != NULL)
		temp_head->next=first_lk;
	else
		temp_head->next=second_lk;
	
	head=save_head->next;
	debug_disp(head,"merge:");
	
	return head;
}



ListNode * merge_sort(ListNode *head) { 
	
	ListNode *mid_pos,*mid_next_llk;
	ListNode *sort_list_1,*sort_list_2;

	if(head == NULL||head->next==NULL)return head;//为空或者为单独一个节点
	
	mid_pos=get_midpos(head,NULL);
	
	mid_next_llk=mid_pos->next;//第二个链表位置
	mid_pos->next=NULL;//拆分成俩个链表

	//debug_disp(head,"list1:");
	//debug_disp(mid_next_llk,"list2:");

	sort_list_1=merge_sort(head);

	sort_list_2=merge_sort(mid_next_llk);
	
	//debug_disp(mid_next_llk,"merge_sort mid_llk:");

	return	 merge(sort_list_1,sort_list_2);//合并
	 
	
}
  
ListNode *sortList(ListNode *head) {
	
	return merge_sort(head);
}

int main()
{
	
    ListNode list1(1), list2(2), list3(3), list4(4), list5(5), list6(6);
    list1.next = &list3;
    list3.next = &list5;
    list5.next = &list4;
    list4.next = &list2;
    list2.next = &list6;
    list6.next = NULL;
    ListNode *result = sortList(&list1);
    debug_disp(&list1,"result:");
    return 1;
} 



本题小结,个人对着归并排序依葫芦画瓢,结果犯了俩个严重的错误

1、将链表拆成俩部分,需注意取下整,否则产生死循环。并且由于是单链表需提前不能回溯。最后划分后需加上NULL;

2、在归并排序时merge_sort(head);merge_sort(mid_next_llk);merge(sort_list_1,sort_list_2);这样写将会产生错误,

原因为:merge后,对原链表已经修改,但head,mid_next_llk仍指向原地方,并非头结点。此处应该使用其返回值,即首结点。

另外一种改进的方法为:外加一个将链表再加一个头结点,对头结点外的节点节点排序即可,不影响头节点!



注:如有不足请各位给予纠正谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值