单向链表排序-归并排序

链表排序中使用归并排序:归并排序不仅保持了它的 O( nlog(n) ) 的时间复杂度,而且它在数组排序中广受诟病的空间复杂度,在链表排序中从 O(n) 降低到 O( log(n) )。

   对于单向链表的二路归并排序,首先是要找到链表的中间节点,将链表等分。我们可以使用快慢指针的方式找到链表的中间节点,即一个指针以一个步长移动,另一个指针使用两个步长移动,当快指针到结尾位置时,慢指针正好在中间位置。接下来是对两个链表进行归并排序。


源程序:

//filename : linklist.h

#ifndef __LINKLIST_H_H_
#define __LINKLIST_H_H_

struct LinkList{
	struct LinkList *next;
	int value;
};

extern struct LinkList *createLinkList(int num);

extern void printLinkList (struct LinkList *list);

extern struct LinkList *merge(struct LinkList *first, struct LinkList *second);

extern struct LinkList *mergeSort(struct LinkList *head);


#endif

源程序:

//filename: linklist.cpp

#include "linklist.h"
#include 
#include 
#include 

/**
 *创建一个带头结点的单向链表
 *@parm[in]: num 链表节点个数
 *@return : 链表头结点 
*/
struct LinkList *createLinkList(int num)
{
	if (num <= 0) {
		printf("could not create LinkList, the input number %d should biger than 0\n");
		return NULL;
	}
	struct LinkList *head = (struct LinkList *)malloc(sizeof(struct LinkList));
	if (NULL == head) {
		printf("Could not malloc enough space\n");
		exit(1);
	}
	struct LinkList *current = head;

	srand( (int)time(0) );
	for (int i = 0; i < num; ++i) {
		struct LinkList *temp = (struct LinkList *)malloc(sizeof(struct LinkList));
		temp->value = rand()%100;
		current->next = temp;
		current = current->next;
	}
	current->next = NULL;
	return head;
}

/**
 *打印输出链表
 *@para[in]: list 有序链表首地址指针 
**/
void printLinkList (struct LinkList *list)
{
	while (list != NULL) {
		printf("%6d  ", list->value);
		list = list->next;
	}
}

/**
 * 按递增顺序,将两个有序单向链表,归并成一个有序单向链表
 * @para[in]: first  有序单向链表首地址指针
 * @para[in]: second 有序单向链表首地址指针
 * @return:   返回排好序后的链表首地址指针
*/
struct LinkList *merge(struct LinkList *first, struct LinkList *second)
{
	struct LinkList *tempsort = (struct LinkList *)malloc(sizeof(struct LinkList));
	if (!tempsort) {
		printf("Could not malloc enough space\n");
		exit(1);
	}
	struct LinkList *curr = tempsort;

	while (first != NULL && second != NULL) {
		if (first->value <= second->value) {
			curr->next = first;
			first = first->next;

		} else {
			curr->next = second;
			second = second->next;
		}
		curr = curr->next;
	}
	if ( NULL != first) {
		curr->next = first;
	}
	if (NULL != second) {
		curr->next = second;
	}
	curr = tempsort->next;
	free(tempsort);
	return curr;
}

/**
 *使用快慢指针,等分单向链表,并调用merge函数对链表排序
 *@para[in/out]: head有序单向链表首地址指针
 *@return: 返回排好序的单链表首地址地址
**/
struct LinkList *mergeSort(struct LinkList *head)
{
	struct LinkList *first = head;
	struct LinkList *second = head;

	if (NULL == first|| NULL == second) {
		return first;
	}
	
	//使用快慢指针将链表等分为两个链表
	while (second->next != NULL && second->next->next != NULL) {
		first = first->next;
		second = second->next->next;
	}
	if (first->next != NULL) {
		second = first->next;
		first->next = NULL;
		first = head;
	}

	//只剩一个节点时,返回
	if (first == second) {
		return first;
	}

	return merge(mergeSort(first), mergeSort(second));
}

源程序:

//filename: main.cpp

#include 
#include 

#include "linklist.h"


int main()
{
	int num = 20;
	struct LinkList *head = NULL;

	head = createLinkList(num);
	printf("Before sort: \n");
	printLinkList(head->next);
	struct LinkList * headnext = mergeSort(head->next);
	head->next = headnext;
	printf("After sort\n");
	printLinkList(head->next);
	return 0;
}



你可能感兴趣的:(算法)