归并排序适用于外部排序,是一种稳定的排序。算法很很好的体现了分治法的思想。
时间复杂度O(nlogn)(最好最坏平均都是它)
空间复杂度O(n) (如果使用的是链表,空间复杂度为O(1))
数组递归实现:
void Merge(int* arr,int* tmp,int left,int right,int rightEnd){
int leftEnd = right-1;
int start = left;
int len = rightEnd - left + 1;
while (left<=leftEnd && right<=rightEnd)
{
if (arr[left] > arr[right]){
tmp[start++] = arr[right++];
}
else{
tmp[start++] = arr[left++];
}
}
while (left <= leftEnd)
{
tmp[start++] = arr[left++];
}
while(right<=rightEnd){
tmp[start++] = arr[right++];
}
for (int i = 0; i < len; i++, rightEnd--){
arr[rightEnd] = tmp[rightEnd];
}
}
void split(int* arr,int* tmp,int left,int rightEnd){
if (left < rightEnd){
int center = (rightEnd + left) / 2;
split(arr, tmp, left, center);
split(arr, tmp, center + 1, rightEnd);
Merge(arr, tmp, left, center + 1, rightEnd);
}
}
void Merge_Sort(int* arr,int len){
int *tmp = (int*)malloc(sizeof(int)*len);
split(arr,tmp,0,len-1);
free(tmp);
}
数组非递归实现:
void Merge(int* arr,int* tmp,int left,int right,int rightEnd){
int leftEnd = right - 1;
int start = left;
while (left <= leftEnd && right <= rightEnd){
if (arr[left] > arr[right]){
tmp[start++] = arr[right++];
}
else{
tmp[start++] = arr[left++];
}
}
while (left <= leftEnd){
tmp[start++] = arr[left++];
}
while (right <= rightEnd){
tmp[start++] = arr[right++];
}
}
void MergeSort(int* arr,int* tmp,int n,int length)//length当前有序子列的长度
{
int i;
for (i = 0; i <= n - 2 * length; i += 2 * length){
Merge(arr,tmp,i,i+length,i+2*length-1);
}
//最后剩下两个子列,进行归并
if (i + length < n){
Merge(arr,tmp,i,i+length,n-1);
}
else{//只剩最后一个子列,不能成对
for (int j = i; j < n; j++){
tmp[j] = arr[j];
}
}
}
void Merge_Sort(int* arr,int n){
int lenght = 1;
int* tmp = (int *)malloc(sizeof(int)*n);
while (lenght < n){
MergeSort(arr,tmp,n,lenght);
lenght *= 2;
MergeSort(tmp,arr,n,lenght);
lenght *= 2;
}
free(tmp);
}
链表实现:
void Merge(ListNode* &left,ListNode* right){
ListNode* tmp = NULL;
ListNode* head = new ListNode(0);
head->next = left;
ListNode* leftPre = head;
while (left != NULL && right != NULL){
if (left->val > right->val){
tmp = right->next;
leftPre->next = right;
right->next = left;
leftPre = leftPre->next;
right = tmp;
}
else{
leftPre = left;
left = left->next;
}
}
while (right!= NULL){
leftPre->next = right;
leftPre = leftPre->next;
right = right->next;
}
left = head->next;
delete head;
}
//对链表进行分割
void split(ListNode* &left,ListNode* &right,ListNode* pHead){
ListNode* low = pHead;
ListNode* high = pHead;
while (high->next != NULL && high->next->next != NULL){
low = low->next;
high = high->next->next;
}
left = pHead;
right = low->next;
low->next = NULL;
}
void Merge_Sort(ListNode* &pHead){
if (pHead == NULL || pHead->next==NULL){
return;
}
ListNode* left = NULL;
ListNode* right = NULL;
split(left,right,pHead);
Merge_Sort(left);
Merge_Sort(right);
Merge(left,right);
pHead = left;//更新pHead
}