【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
#include <iostream>
using namespace std;
//归并算法
/**
一句箴言:将待排序数据一分为二,二分为四,四分为八,递归下去,直至每份为1个元素,这一个元素自身一定为有序的,然后再将分了的两两合并为有序数组,最终变成一个有序数组。
方法:递归拆分并两两合并为有序数组。其中合并时候需要将待合并的两组数据拷贝出来,指定左待归并数据索引i,右待归并数据索引j, k为原数组需重新指定值得索引
**/
void _merge(int arr[], int l, int mid, int r) {
//归并前判断是否分割的两数组已经左边小右边大了
if (arr[mid+1] > arr[mid]) {
return;
}
//首先需要拷贝出待归并区间的数据 区间为索引l到 r
int aux[r - l + 1];
for (int i = l ; i <= r; i++) {
aux[i - l] = arr[i];
}
/**
// 注释的是去除掉偏移量l后的数组 求解法
int max = r -l;
int newMid = (max - min) / 2;
int i = 0,j = newMid + 1;
//遍历原数组l到 r 这个区间,走待归并的两个区间里选择最小的去填充覆盖
for (int k = l; k <= r; k++) {
//当左边的都已经赋值完,索引已经越过中间点,则只剩下右边的了
if (i > newMid ) {
arr[k] = aux[j];
j++;
} else if (j > max) {
arr[k] = aux[i];
i++;
} else if(aux[i] < aux[j]) {
arr[k] = aux[i];
i++;
} else {
arr[k] = aux[j];
j++;
}
}
**/
int i = l,j = mid + 1;
//遍历原数组l到 r 这个区间,走待归并的两个区间里选择最小的去填充覆盖
for (int k = l; k <= r; k++) {
//当左边的都已经赋值完,索引已经越过中间点,则只剩下右边的了
if (i > mid ) {
arr[k] = aux[j-l];
j++;
} else if (j > r) {
arr[k] = aux[i-l];
i++;
} else if(aux[i-l] < aux[j-l]) {
arr[k] = aux[i-l];
i++;
} else {
arr[k] = aux[j-l];
j++;
}
}
}
void mergeSort(int arr[], int l, int r) {
//递归则首先要找到跳出条件
if (l >= r) {
return ;
}
//一分为二,递归调用自己排序
int mid = (r + l) / 2;
mergeSort(arr, l, mid);
mergeSort(arr, mid+1, r);
//归并
_merge(arr, l, mid, r);
}
int main() {
int arr[10] = {10,9,8,7,6,5,4,3,2,1};
mergeSort(arr, 0, 9);
for(int i =0; i< 10; i++) {
cout << arr[i] << " ";
}
return 0;
}
来源:oschina
链接:https://my.oschina.net/u/214052/blog/3149101