前言:
理论很枯燥、文字更烦人 ,但是这里将理论知识告诉大家并不是让大家一上来就看干巴巴的文字,因为我在代码中能注释的地方都进行了注释希望大家先跟着注释打一遍,不要着急,当在黑色的星空中出现了结果,你就会为之振奋,有了继续学下去的勇气,当你对代码中的思想有了较深的理解后,再回过头来看这些理论文字,我相信会好很多,最后一句话:书读百遍,其义自见。归并排序:
1.
归并排序(merge sorting)简单地将原始序列划分为两个子序列,然后分别对每个子序列递归排序,最后再将有序子序列合并。
归并排序主要步骤为:
(1)将序列划分为两个子序列。
(2)分别对这两个子序列递归进行归并排序。
(3)将这两个已排好序的子序列合并为一个有序序列,即归并过程。
2.归并排序也是一种基于分治法的排序。
快速排序侧重于“分”(含“治”),即用轴值分割子序列的过程,没有明显的“合”。归并排序的“分”很简单,就是拦腰折断,一分两半,它更多的侧重的是“治”和“合”。
3.归并排序中的“治”和“合”-
两个有序子序列的归并
:每次比较子序列头,取出较小的进入序列;其后次小记录顶上来,继续比较两个子序列头,取出较小的进入结果序列;重复上述过程,直到其中一个子序列为空,剩余子序列中的记录就可以直接进入结果序列。
4.归并排序中的分 - 不断的将原始序列分为越来越多的子序列,直到子序列长度为1,停止划分。
完整代码如下:(递归实现归并排序)
//#pragma once //MergeSort - 归并排序(分治思想) #include <iostream> using namespace std; //有序子列的归并 - 治 //A - 待排数组、TmpA - 临时数组、L - 左边起始位置、R - 左边起始位置、RightEnd - 左边终点位置 void Merge(int A[], int TmpA[], int L, int R, int RightEnd) { int LeftEnd, ElementNum, Tmp; LeftEnd = R - 1; //左边终点位置 Tmp = L; //归并后数组的起始位置 ElementNum = RightEnd - L + 1; //元素个数 //归并过程 while (L <= LeftEnd && R <= RightEnd) { if (A[L] <= A[R]) TmpA[Tmp++] = A[L++]; else TmpA[Tmp++] = A[R++]; } //解决有剩余元素的子列 while (L <= LeftEnd) TmpA[Tmp++] = A[L++]; while (R <= RightEnd) TmpA[Tmp++] = A[R++]; //将临时数组中排好序后的元素重新赋值给原数组A for (int i = 0; i < ElementNum; i++, RightEnd--) A[RightEnd] = TmpA[RightEnd]; } //采用递归函数的方式实现 - 分 //A - 待排数组、TmpA - 临时数组、L - 数组左边起始位置、RightEnd - 原数组左边终点位置 void Msort(int A[], int TmpA[], int L, int RightEnd) { int Center; if (L < RightEnd) // ==是只剩一个元素,不需要再分 { //分 Center = (L + RightEnd) / 2; Msort(A, TmpA, L, Center); Msort(A, TmpA, Center + 1, RightEnd); //治 Merge(A, TmpA, L, Center + 1, RightEnd); } } //为归并排序函数设置统一接口 void MergeSort(int A[], int N) { int *TmpA; //临时数组 TmpA = new int[N]; if (TmpA) { Msort(A, TmpA, 0, N - 1); delete[] TmpA; } else cout << "空间不足" << endl; } int main() { int N, i; //待排元素个数 cin >> N; int A[N]; //输入 for(i = 0; i < N; i++) { cin >> A[i]; } //归并排序 MergeSort(A,N); //输出结果 for(i=0;i < N; i++) { cout << A[i] << " "; } cout << endl; return 0; }