概述
归并排序是创建在归并操作上的一种有效的排序算法,效率为O(nlogn),1945年由冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。通过将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
归并排序效率虽然较高,但所需的空间复杂度为O(n),典型的空间换时间。
算法描述
把长度为n的输入序列分成两个长度为n/2的子序列;
对这两个子序列分别采用归并排序,直到子序列无法再分。
将两个排序好的子序列合并成一个最终的排序序列。
归并排序C/C++代码:
/**
* 合并操作
* @param arr 元素数组
* @param left 左子数组起点
* @param mid 左子数组终点
* @param right 右子数组终点
*/
void Merge(int arr[],int left,int mid,int right)
{
int len=right-left+1;
int *temp = new int[len]; //缓存临时元素序列
int index=0;
int left_index=left; //保存左子序列的索引
int right_index=mid+1; //保存右子序列的索引
while(left_index<=mid && right_index <= right)
{
temp[index]=arr[left_index]<=arr[right_index]?arr[left_index++]:arr[right_index++]; // 带等号可保证归并排序的稳定性
index++;
}
while (left_index<=mid)
{
temp[index]=arr[left_index++];
index++;
}
while (right_index<=right)
{
temp[index]=arr[right_index++];
index++;
}
for (int i = 0; i < len; i++) {
arr[left + i] = temp[i];
}
}
/**
* 归并排序
* 最差时间复杂度 O(nlogn)
* 最优时间复杂度 O(nlogn)
* 平均时间复杂度 O(nlogn)
* 空间复杂度 O(n)
* 稳定性 稳定
* @param arr 数组
* @param size 长度
*/
void MergeSort(int arr[], int left,int right)
{
if(left==right)return; //当待排序的序列的左索引和右索引相同,即该序列的长度为1时,递归开始回溯,进行Merge操作
int mid = (left + right) / 2; //将元素序列分为两个子序列
MergeSort(arr, left, mid); //对左序列进行归并排序
MergeSort(arr, mid+1, right); //对右序列进行归并排序
Merge(arr,left,mid,right); //对左右序列进行合并
//打印具体排序流程
for(int i = left;i<=right;i++)
{
std::cout << arr[i] <<" ";
}
cout<<endl;
}
元素序列{3,44,38,5,47,15,36,26,27,2,46,4,19,50,48}的归并排序动态流程图如下: