这两天学习了归并排序,特此来记录总结。
归并排序的思想通过将一组待排序数据一分为多组有序数列(已经排好序的数列),然后再将各个有序数列逐对按照一定规则进行归并,最终得到整个有序数列。归并排序是一个十分稳定的排序方法,它的时间复杂度永远都是O(nlogn),但是作为代价,归并算法需要重新创建一条跟待排序数列一样长度的数组,其空间复杂度就随之提高。根据此特点,归并排序常被用在外排序1,基本不会用在内排序2。
1.外排序:指在排序期间全部对象太多,不能同时存放在内存中,必须根据排序过程的要求,不断在内,外存间移动的排序。
2.内排序:指在排序期间数据对象全部存放在内存的排序。
主要实现步骤:
一. 将数组中每一个数都看成最初的一个有序数列,开始两两合并
二. 合并时从两个队列的第一位选择最小的一个放入待完整的有序数组中,不断比较并提取较小的那个数,直至两个队列的数都被选入。
用语言实在不太好表达,下面是说明图:
图1
归并排序有递归跟非递归两种实现方法。Talk is cheap, show you the code.
头文件Sort.h:
1 //自己编写的各种排序算法的头文件。
2 #ifndef _SORT_H
3 #define _SORT_H
4 //冒泡排序
5 class bubble_sort{
6 private:
7 int *Array,Length;
8 public:
9 bubble_sort(int *Array1,int Length);
10 int *sort_bubble();
11
12 };
13 //归并排序
14 class merge_sort{
15 public:
16 static void sort_merge(int Array1[], int Array2[], int Left, int Rightend, int Right,int recursion);
17 static void Merge(int Array1[], int Array2[], int Left, int Rightend);//递归方法
18 static void Merge_pass(int Array1[], int Array2[], int ordered_len,int Length);
19 static void Merge1(int Array1[], int Array2[], int Length);//非递归方法
20 };
21 #endif
//对函数中函数的描述文件。
1 #include "Sort.h"
2 /*下面是对两个有序的数组进行归并的函数,middle
3 是在一个长数组中的分隔点,将一个数组分成两个数组进行归并。*/
4 void merge_sort::sort_merge(int Array1[], int Array2[], int Left, int Rightend, int Right,int recursion)
5 {
6 int Leftend = Right - 1;
7 int i = Left;
8 int Length = Rightend - Left + 1;
9 while (Left<=Leftend&&Right<=Rightend)//考虑在两边数组没有任何一个数组全都归并到大数组路面去的情况。
10 Array2[i++] = Array1[Left] < Array1[Right] ? Array1[Left++] : Array1[Right++];
11 while (Right <= Rightend)
12 Array2[i++] = Array1[Right++];
13 while (Left <= Leftend)
14 Array2[i++] = Array1[Left++];
15 if (recursion)//判断是否递归调用。
16 {
17 for (int j = 0; j < Length; j++, Rightend--)
18 Array1[Rightend] = Array2[Rightend];
19 }
20 }
21 void merge_sort::Merge(int Array1[], int Array2[], int Left, int Rightend)
22 {
23 if (Rightend > Left)
24 {
25 int middle = (Left + Rightend) / 2;
26 Merge(Array1, Array2, Left, middle);
27 Merge(Array1, Array2, middle + 1, Rightend);
28 merge_sort::sort_merge(Array1, Array2, Left, Rightend, middle + 1,1);
29 }
30 }
31 void merge_sort::Merge_pass(int Array1[], int Array2[], int ordered_len,int Length)
32 {
33 int i = 0;
34 for (; i <= Length - 2 * ordered_len; i += 2 * ordered_len)
35 merge_sort::sort_merge(Array1, Array2, i, i + ordered_len, i + 2 * ordered_len - 1,0);
36 if (i < Length - ordered_len)
37 merge_sort::sort_merge(Array1, Array2, i, i + ordered_len, Length - 1,0);
38 else
39 for (; i < Length; i++)
40 Array2[i] = Array1[i];
41 }
42 void merge_sort::Merge1(int Array1[], int Array2[], int Length)
43 {
44 int ordered_len = 1;//初始有序长度皆为1。
45 while (ordered_len < Length)
46 {//注意:上下两次调用参数Array1和Array2位置互换,就是为了在不断排序后最终将结果存在Array1中。
47 merge_sort::Merge_pass(Array1, Array2, ordered_len, Length);
48 ordered_len *= 2;
49 merge_sort::Merge_pass(Array2, Array1, ordered_len, Length);
50 ordered_len *= 2;
51 }
52 }
main.cpp:
1 /************************* 2 Write by Leo Lv 3 2019.3.31 4 Merge sort 5 *************************/ 6 #include <iostream> 7 #include "Sort.h" 8 using namespace std; 9 int main() 10 { 11 int Array1[10] = { 4, 700, 80, 2000, 6, 3, 7, 10, 5,0 }; 12 int *Array2; 13 Array2 = (int*)malloc(11*sizeof(int)); 14 if (Array2 != NULL)//判断空间是否创建成功 15 { 16 merge_sort::Merge(Array1, Array2, 0, 9); 17 18 cout << "递归算法结果如下" << endl; 19 for (int i = 0; i < (sizeof(Array1) / sizeof(int)); i++) 20 { 21 cout << Array1[i] << endl; 22 } 23 merge_sort::Merge1(Array1, Array2, (sizeof(Array1) / sizeof(int))); 24 cout << "非递归算法结果如下" << endl; 25 for (int i = 0; i < (sizeof(Array1) / sizeof(int)); i++) 26 { 27 cout << Array1[i] << endl; 28 } 29 free(Array2);//记得释放动态空间。 30 system("pause"); 31 return 0; 32 } 33 else 34 return -1; 35 36 }
下面结合代码介绍,在头文件中merge_sort这个类中,我定义了四个public的函数,分别为:
1.static void sort_merge(int Array1[], int Array2[], int Left, int Rightend, int Right,int recursion);
2.static void Merge(int Array1[], int Array2[], int Left, int Rightend);//递归方法
3.static void Merge_pass(int Array1[], int Array2[], int ordered_len,int Length);
4.static void Merge1(int Array1[], int Array2[], int Length);//非递归方法
void sort_merge(int Array1[], int Array2[], int Left, int Rightend, int Right,int recursion)函数是完成图1中操作的函数,其中int Array1是输入的待排序数组,Array2是用作临时储存的数组,作为参数传递可以避免浪费过多空间Left和Right分别是左边队列起始点跟右边队列起始点,Rightend是指右边(也就是整个队列的终点),recursion是递归标识符1代表递归,0代表非递归。
static void Merge(int Array1[], int Array2[], int Left, int Rightend)函数是完成递归的归并排序调用函数,其参数定义参考第一个函数的参数。
static void Merge_pass(int Array1[], int Array2[], int ordered_len,int Length)函数是完成非递归队列合并的函数,参数中前两个数组参数的定义同上,ordered_len是定义当前有序对联长度,Length是指待排数据的总长度。
static void Merge1(int Array1[], int Array2[], int Length);函数的参数比较简单,定义同上。
代码细节部分的含义,在代码的注释中有解释。相信大家参照着代码能读懂归并算法的思想的,可能是本人理解还不够透彻,解释的很清楚实在费力气- -,若有大佬发现不足之处,请指正,谢谢!