归并排序首先找中间节点。如果是链表,利用快慢指针寻找中间节点,如果是数组,直接使用(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。
(本文完)