归并排序(Merge Sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

  归并操作(Merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。归并排序有多路归并排序、两路归并排序 , 可用于内排序,也可以用于外排序。这里仅对内排序的两路归并方法进行讨论。

  归并排序的步骤如下:

  1)Divide: 将待排序序列(原问题)分成两个规模大致相等的子序列(子问题);

  2)Conquer: 递归地排序两个子序列,当子序列规模足够小的时候直接完成排序;

  3)Combine: 合并两个已序的子序列得到原序列的排序结果。

  动画演示可以参照这个网址

  对于归并排序,最重要的就是归并操作。对于归并操作,可作如下理解:

  1)针对输入的两段等合并的有序子序列,我们申请两个变量,分别对它们进行备份;

  2)将这两段序列有序地合并到原序列中。因为这段序列是有序的,所以,当我们要判断将哪一个数据填入原序列时,只需判断两段序列中位置最低、且尚未被填入原序列的数据的大小,再将较小的数据填入原序列就可以了。

  归并操作定义如下:

void MergeSort::merge(int low, int mid, int high)

  数组arr从low到mid有序,从mid+1到high有序,合并这两部分,使得从low到high有序,且这个有序序列仍然放在arr的从low到high下标里。

  一个比较详细的程序如下:

 1 void MergeSort::mergesort(int low, int high)
 2 {
 3     if (high <= low)    return;
 4 
 5     int mid = (low + high) / 2;
 6     mergesort(low, mid);
 7     mergesort(mid + 1, high);
 8     merge(low, mid, high);
 9 }
10 
11 void MergeSort::merge(int low, int mid, int high)
12 {
13     int nOfLeft = mid - low + 1;
14     int nOfRight = high - mid;
15     int * copyOfLeft = new(nothrow) int[nOfLeft];
16     int * copyOfRight = new(nothrow) int[nOfRight];
17     assert(copyOfLeft != nullptr);
18     assert(copyOfRight != nullptr);
19 
20     // Copy left part
21     int i;
22     for (i = 0; i < nOfLeft; i++)
23     {
24         copyOfLeft[i] = arr[i + low];
25     }
26 
27     // Copy right part
28     int j;
29     for (j = 0; j < nOfRight; j++)
30     {
31         copyOfRight[j] = arr[j + mid + 1];
32     }
33 
34     // 在这里需要意识到的一个问题:copyOfLeft及copyOfRight已经是“有序”序列
35     // Merge
36     i = 0;
37     j = 0;
38     for (int k = low; k < high + 1; k++)
39     {
40         if (i > nOfLeft - 1)
41         {
42             arr[k] = copyOfRight[j];
43             j++;
44         }
45         else if (j > nOfRight - 1)
46         {
47             arr[k] = copyOfLeft[i];
48             i++;
49         }
50         else if (less(copyOfLeft[i], copyOfRight[j]))
51         {
52             arr[k] = copyOfLeft[i];
53             i++;
54         }
55         else
56         {
57             arr[k] = copyOfRight[j];
58             j++;
59         }
60     }
61 
62     delete[] copyOfLeft;
63     delete[] copyOfRight;
64  }
View Code

相关文章: