用归并排序实现单链表的排序

今天做了百度的一套数据挖掘的笔试题,其中有一道对单链表进行归并排序,因为刚学归并排序的时候是针对数组来说,所以这道题着实费了一点心思。

考点:1归并算法;2单双步求中点;3链表指针的操作,以及边界空指针问题;4内存分配与回收;

单链表与数组相比只能顺序访问每个元素,因此在使用二路归并排序时关键在于找到链表的中间结点将链表一分为二:可以利用快慢指针同时遍历单链表,当步长为2的指针指向链表最后一个结点或者最后一个结点的下一个结点时,步长为1的指针即指向链表的中间结点。然后是两个有序单链表的合并问题。时间复杂度为O(N*logN),空间复杂度为O(1)。注意空间复杂度,此时是单链表的一个优势,直接通过更改链表指针完成排序,而不需另外分配空间,这就是考察了人的思维了。不说多的,非常感谢网上一些老师的答案和分析,让我学会了很多知识点,谢谢啦~

// ListNodeMerge_sort.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<cstdlib>
#include <iostream>
#include <time.h>
using namespace std;

struct Node
{
	int v;
	struct Node* next;
 };
/*分割一个链表为两部分,通过指针返回结果,使用单双步指针*/
 void FrontBackSplit(Node *source,Node** front,Node** back)
{	 
	 Node *slow=NULL, *fast=NULL;
	 if (source == NULL || source->next == NULL)
	 {
		 /*length<2*/
		 *front = source;
		 *back = NULL;
	 }
	 else
	 {	
		 slow = source;
		 fast = source->next;
	 }

	while (fast != NULL&&fast->next != NULL)
	{
		fast = fast->next;
		if (fast != NULL)
		{
			slow = slow->next;
			fast = fast->next;
		}	
	}
	/*slow在中间位置的前面*/
	*front = source;
	*back = slow->next;
	slow->next=NULL;	//完成一分为二;
}

Node* Merge(Node *source1, Node *source2)
{
	Node *temp=NULL ;
	if (source1 == NULL)
		return (source2);
	else if (source2 == NULL)
	return (source1);

	if (source1->v <= source2->v)
	{
		temp = source1;
		temp->next = Merge(source1->next, source2);
	}
	else
	{
		temp = source2;
		temp->next = Merge(source1, source2->next);
	}
	return temp;
}

void mergesort(Node **L)
{
	Node *P = *L;
	if (P == NULL || P->next == NULL) return;
	Node *Pa, *Pb;
	FrontBackSplit(P,&Pa,&Pb);	
	mergesort(&Pa);
	mergesort(&Pb);
	*L=Merge(Pa, Pb);
}

Node *merge_sort(Node* L)
{
	mergesort(&L);
	return NULL;
}

void printList( Node * Node)
{
	while (Node != NULL)
	{
		printf("%d ", Node->v);
		Node = Node->next;
	}
}
void DestroyList(Node *L) 
{
	Node *p, *q;
	p = q = L;
	while (p != NULL) {
		q = q->next;
		free(p);
		p = q;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	int len = 10, i;
	Node *L;
	Node *p;
	if ((L = (Node*)malloc(sizeof(Node))) == NULL) {
		cerr << "Error in allocate memory!" << endl;
		return -1;
	}
	srand(time(NULL));
	L->v = rand() % 1000; 
	L->next = NULL;
	for (i = 1; i < len; i++) 
	{
		if ((p = (Node*)malloc(sizeof(Node))) == NULL) 
		{
			cerr << "Error in allocate memory!" << endl;
			DestroyList(L);
			return -1;
		}
		p->v = rand() % 1000;
		p->next = L->next;
		L->next = p;
	}
	cout << "The list before sorting:" << endl;
	printList(L);

	merge_sort(L);
	cout << "\nThe list after sorting:" << endl;
	printList(L);

	DestroyList(L);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值