归并排序C++版

归并排序首先找中间节点。如果是链表,利用快慢指针寻找中间节点,如果是数组,直接使用(start+end)/2找到中间节点位置,链表版本中,需要O(1)的空闲复杂度去存一个头节点,而数组版本,需要O(N)的空间复杂度需要构造一个缓存数组存下所有节点。两种版本的实现时间复杂度都是O(N*logN)。下面看代码

数组版本:

/* 归并排序的空闲消耗比较大 */
bool SortAlgorithms::mergeSort(int array[], int tempArray[], int left, int right){
	if(left==right)
		return false;
	int middle=(left+right)/2;
	mergeSort(array,tempArray,left,middle);
	mergeSort(array,tempArray,middle+1,right);
	merge(array,tempArray,left,right,middle);
}

void SortAlgorithms::merge(int array[], int tempArray[], int left, int right, int middle){
	for(int i=left;i<=right;i++){
		tempArray[i]=array[i];
	}

	int k=left;
	int i=left;
	int j=middle+1;
	while((i<=middle)&&(j<=right)){
		if(tempArray[i]>tempArray[j]){
			array[k]=tempArray[j];
			j++;
			k++;
		}
		else{
			array[k]=tempArray[i];
			i++;
			k++;
		}
	}
	while(i<=middle){
		array[k]=tempArray[i];
		i++;
		k++;
	}
	while(j<=right){
		array[k]=tempArray[j];
		j++;
		k++;
	}
	prt(array);
}

void SortAlgorithms::radixSort(){

}

void SortAlgorithms::prt(int *arr){
	for(int i=0;i<20;i++){
		cout<<" "<<arr[i];
	}
	cout<<endl;
}

测试:

sort->mergeSort(waitingforSort,tempArray,0,19);
sort->prt(waitingforSort);

链表版本:

#include "List.h"

List::List() {
	// TODO Auto-generated constructor stub

}

List::~List() {
	// TODO Auto-generated destructor stub
}

void List::init(){
	/* for test, there is 11 nodes */
	head=(ListNode *)malloc(sizeof(ListNode));
	head->val=9;
	head->next=0;
	ListNode *node;
	for(int i=0;i<10;i++){
		node=(ListNode *)malloc(sizeof(ListNode));
		node->val=i;
		node->next=head->next;
		head->next=node;
	}

	l1=(ListNode *)malloc(sizeof(ListNode));
	l1->val=1;
	l1->next=0;
	for(int i=0;i<10;i++){
		node=(ListNode *)malloc(sizeof(ListNode));
		node->val=30-i*3;
		node->next=l1->next;
		l1->next=node;
	}

	l2=(ListNode *)malloc(sizeof(ListNode));
	l2->val=1;
	l2->next=0;
	for(int i=0;i<10;i++){
		node=(ListNode *)malloc(sizeof(ListNode));
		node->val=20-i*1;
		node->next=l2->next;
		l2->next=node;
	}
}

ListNode* List::getRoot(){
	return head;
}

/*
 * fast and slow pointer, it's great! divided into two parts.
 * 2*n+1:
 *   fast: n times reach 1+2*n
 *   slow: n times reach 1+n(last node in first list)
 * 2*n:
 *   fast: n-1 times reach 2*n-1
 *   slow: n-1 times reach n(last node in first list)
 * */
ListNode* List::findMiddle(ListNode *head){
	ListNode *fast=head;
	ListNode *slow=head;
	while(fast->next!=0&&fast->next->next!=0){
		fast=fast->next->next;
		slow=slow->next;
	}
	return slow;
}

ListNode *List::mergeTwoList(ListNode *left, ListNode *right){
	ListNode *ret=(ListNode *)malloc(sizeof(ListNode));
	ret->val=-1;ret->next=0;
	ListNode *r=ret;
	while(left!=0&&right!=0){
		if(left->val<right->val){
			ret->next=left;
			ret=left;
			left=left->next;
		}
		else{
			ret->next=right;
			ret=right;
			right=right->next;
		}
	}
	while(left!=0){
		ret->next=left;
		ret=left;
		left=left->next;
	}
	while(right!=0){
		ret->next=right;
		ret=right;
		right=right->next;
	}
	return r->next;
}

ListNode *List::sortList(ListNode *head){
	if(head==0||head->next==0)
		return head;
	ListNode *first=head;
	ListNode *middle=findMiddle(head);
	ListNode *second=middle->next;
	middle->next=0;
	ListNode *li1=sortList(first);
	ListNode *li2=sortList(second);
	return mergeTwoList(li1,li2);
}

void List::print(ListNode *h){
	ListNode *node=h;
	while(node!=0){
		cout<<" : "<<node->val;
		node=node->next;
	}
	cout<<endl;
}

如果是排序多个已经排序的链表,可以都转换为排序两个,但是还有种应该更快的方法,采用一个排序的buffer。

(本文完)

点赞