归并排序是将俩个有序的序列合成一个序列的过程,在合并的时候俩个序列越有序合并的速度越快,归并排序的应用有很多,首先是应用在求逆序数上,我会将我自己做过的俩道用归并排序AC的题目放上来一道是(求逆序数)另一道是(稿件整理的题目2017ICPC内蒙古自治区省赛的题目当时还是大一萌新不会做,放到现在大二马上大三的我来说简直简单的不行,咳咳不说了继续我们的归并排序思路)
它的原理就是先拆分数组里的元素:
比如 6, 5, 2, 1, 3, 8, 9;
第一列: 6 5 2;
第二列:1 3 8 9;
然后第一列继续拆分一直到6 5 2的时候然后开始合并
俩个数组合并比较6和5 6比5大那么temp[]里面就存的是5 6(temp是临时数组,从小到大的顺序存)
然后5 6和2比较最后是2 5 6
第二列也一样因为1 3 8 是有序的所以不用拍最后是1 3 8
最后第一第二列合并
2 5 6
1 3 8 9
First_a是第一列的起始位置
Second_a是第二列的起始位置
俩个数组先比较2比1大所以Second_a指针后移并且把1放到临时数组然后2和3比较然后放2然后5和3比较然后放3等等
最后第一列存完了但是 第二列的 9 没有存所以需要处理一下在存一下(这里说一下为什么要直接存因为我每个数组都是有序的数组所以后面的就比前面的大所以放心直接存就好了当初学的时候这里纠结了好久)。
不多说上代码:
//合并算法 从小到大合并 ////里面参数的是存放数据的数组,起始位置,中间位置,结束位置,临时数组 void Merge(int arr[], int start, int mid, int end, int temp[]) { int First_a = start; int Second_a = mid + 1; //表示辅助空间有多少元素 int length = 0; //合并俩个有序序列 //如果俩个数组有一个到达了末尾,就结束是因为 while(First_a <= mid && Second_a <= end) { //如果第一个数组小于第二个那么我就放第一个数组里面的 if(arr[First_a] < arr[Second_a]) { temp[length++] = arr[First_a++]; } else { temp[length++] = arr[Second_a++]; } } //因为有可能有一个结束另一个数组没放完所以要处理一下 while(First_a <= mid) { temp[length++] = arr[First_a++]; } while(Second_a <= mid) { temp[length++] = arr[Second_a++]; } //最后再把辅助空间里的值赋值个原空间 for(int i = 0; i < length; i++) { //因为我是从start开始的所以要start + i开始 arr[start + i] = temp[i]; } } //归并排序 //里面参数的是存放数据的数组,起始位置,结束位置,临时数组 void Merge_Sort(int arr[], int start, int end, int temp[]) { if(start >= end) { return ; } int mid = (start + end) / 2; //左半边归并 Merge_Sort(arr, start, mid, temp); //右半边归并 Merge_Sort(arr, mid + 1, end, temp); //合并 Merge(arr, start, mid, end, temp); }
//完整的代码如下:
# include <iostream> # include <numeric> # include <algorithm> # include <functional> # include <list> # include <map> # include <set> # include <stack> # include <deque> # include <queue> # include <vector> # include <ctime> # include <cstdlib> # include <cmath> # include <string> # include <cstring> using namespace std; //创建数组里面的参数是要建立能存多少个数据的数组 int* Creat_Arr(int length) { int *arr = (int *)malloc(sizeof(int) * length); // int *arr = new int [length]; srand((unsigned int)time(NULL)); for(int i = 0; i < length; i++) { arr[i] = rand() % 10; } return arr; } //打印数组传的参数一个是数组,一个是数组的长度 void Print(int arr[], int length) { for(int i = 0; i < length; i++) { i != length - 1 ? cout << arr[i] << " " : cout << arr[i] << endl; } } //合并算法 从小到大合并 ////里面参数的是存放数据的数组,起始位置,中间位置,结束位置,临时数组 void Merge(int arr[], int start, int mid, int end, int temp[]) { int First_a = start; int Second_a = mid + 1; //表示辅助空间有多少元素 int length = 0; //合并俩个有序序列 //如果俩个数组有一个到达了末尾,就结束是因为 while(First_a <= mid && Second_a <= end) { //如果第一个数组小于第二个那么我就放第一个数组里面的 if(arr[First_a] < arr[Second_a]) { temp[length++] = arr[First_a++]; } else { temp[length++] = arr[Second_a++]; } } //因为有可能有一个结束另一个数组没放完所以要处理一下 while(First_a <= mid) { temp[length++] = arr[First_a++]; } while(Second_a <= mid) { temp[length++] = arr[Second_a++]; } //最后再把辅助空间里的值赋值个原空间 for(int i = 0; i < length; i++) { //因为我是从start开始的所以要start + i开始 arr[start + i] = temp[i]; } } //归并排序 //里面参数的是存放数据的数组,起始位置,结束位置,临时数组 void Merge_Sort(int arr[], int start, int end, int temp[]) { if(start >= end) { return ; } int mid = (start + end) / 2; //左半边归并 Merge_Sort(arr, start, mid, temp); //右半边归并 Merge_Sort(arr, mid + 1, end, temp); //合并 Merge(arr, start, mid, end, temp); } int main(int argc, char *argv[]) { int n; cout << "请输入你想创建的数组:"; cin >> n; int *temp = new int [n]; int *arr = Creat_Arr(n); cout << endl << "原数组:" << endl; Print(arr, n); cout << "排序后:" << endl; Merge_Sort(arr, 0, n - 1, temp); Print(arr, n); return 0; }
结果如下: