七、归并排序
(3/3)第三个O(nlogn)的排序算法
原理:将已经有序的子序列合并,得到有序的完整序列
1.如何得到有序的子序列:继续划分,有序的子序列是由更小的有序子序列合并而成。很明显这是一个递归过程,划分直到子序列只有一个元素,一个元素即有序。
2.如何将有序子序列合并成有序长序列:比较两个序列中的元素,小的先取出放在前面即可,运用双指针容易实现
void MergeSort(vector<int>& a, int n) {//归并排序主函数
vector<int> temp(n);//申请临时数组,用于最后归并一步的临时存放
msort(a, temp, 0, n-1);
}
void msort(vector<int>& a, vector<int>& temp, int low, int high) {//用于递归的函数
if (low == high) return; // 如果只有一个元素,那么不需要继续划分
// 只有一个元素的区域,本生就是有序的,只需要被归并即可
else {
int mid = (low + high) / 2;
msort(a, temp, low, mid);
msort(a, temp, mid + 1, high);//分治思想,继续递归划分左半区与右半区
merge(a, temp, low, mid, high);//归并两个有序的子序列
}
}
void merge(vector<int>& a, vector<int>& temp, int low, int mid, int high) {//用于合并子序列的函数
int i = low, j = mid + 1, k = low;//左半区第一个未被排序的元素
//右半区第一个未被排序的元素,临时数组下标
while (i <= mid && j <= high) {
if (a[i] < a[j]) temp[k++] = a[i++];// 左半区第一个剩余元素更小
else temp[k++] = a[j++];// 右半区第一个剩余元素更小
}//归并过程
while(i<=mid) temp[k++] = a[i++]; // 合并左半区剩余的元素
while(j<=high) temp[k++] = a[j++];// 合并右半区剩余的元素
while (low <= high) {// 把临时数组中合并后的元素复制回原来的数组
a[low] = temp[low];
low++;
}
}