归并排序个人理解

  归并排序(Merge Sort)采用了分治思想(分而治之)

  分治思想即为了解决一个特定的问题,将问题分为很多个小的子问题,之后对这些子问题进行递归,一边递归一边拆分子问题直至无法拆分。拆分完毕后,将这些独立的子问题解决,将每个子问题解决的答案加在一起就是一整个问题的答案。

  首先是归并排序在《算法导论》中的一个简单表现例子:

  有两幅扑克牌背面朝下放在桌子上,最小的牌在牌堆的最上面。目的是将两幅牌面朝下(最小牌在下)合成一副牌盖在桌子上。我们要做的就是比较两副牌牌堆顶谁点数小,就把谁的牌堆顶牌拿下背朝上盖在桌子上。依次类推,直至两个牌堆中的一个为空,之后要做的就是把剩下的牌堆不需要进行任何操作,背朝上盖在目标牌堆上就好了。

  上面的过程就是分治思想中的

  程序中的数组同理,假设我们有串数据,内容是5,2,4,7,1,3,2,6,我把数组均分成两部分,但两部分数组仍然是无序的,为了使两个数组有序(这样才能做到上面的治,即数组第一个元素作比较),我们需要把每个子数组分到直至只有一个元素。最后我们能分出来八个独立元素,两两之间作比较,就能合并出四个有两个元素的有序数组,不停合并(合并过程中穿插着子数组之间的归并排序,依次比较两个数组的最小值谁更小,将其放入到要合并的数组当中去)到只有一个八元素数组。

  归并排序个人理解

  C++代码

 1 void mergeSort(vector<int>& nums) {
 2     int left = 0, right = nums.size() - 1;
 3     vector<int> temp(nums.size());                //临时数组,用于存放递归过程中的数据
 4     mergeSortStep(nums, left, right, temp);
 5 }
 6 void mergeSortStep(vector<int>& nums, int left, int right, vector<int>& temp) {
 7     //递归终止条件,即分到只剩下一个元素
 8     if (left < right) {
 9         int middle = (left + right) / 2;                //均分
10         mergeSortStep(nums, left, middle, temp);        //对分出来的左半部分继续均分
11         mergeSortStep(nums, middle + 1, right, temp);    //对分出来的右半部分继续均分
12         merge(nums, left, middle, right, temp);            //归并操作
13     }
14 }
15 void merge(vector<int>& nums, int left, int middle, int right, vector<int>& temp) {
16     int leftIndex = left, rightIndex = middle + 1;
17     int index = left;    //临时数组的索引值
18     //比较操作,小的元素依次放到临时数组temp中,直至左右两部分有一部分空了
19     while (leftIndex != middle + 1 && rightIndex != right + 1) {
20         if (nums[leftIndex] <= nums[rightIndex]) {
21             temp[index] = nums[leftIndex];
22             index++;
23             leftIndex++;
24         }
25         else {
26             temp[index] = nums[rightIndex];
27             index++;
28             rightIndex++;
29         }
30     }
31     //找到没空的那部分,依次放入到temp临时数组中
32     if (leftIndex == middle + 1) {
33         for (int i = rightIndex; i <= right; i++, index++) {
34             temp[index] = nums[i];
35         }
36     }
37     else if(rightIndex == right + 1){
38         for (int i = leftIndex; i <= middle; i++, index++) {
39             temp[index] = nums[i];
40         }
41     }
42     //一次归并操作完成,把之前操作过的部分赋值到原始数组中
43     for (int i = left, j = left; i <= right; i++, j++) {
44         nums[i] = temp[j];
45     }
46 }

  因为要提前建立一个临时数组,所以空间复杂度是O(N),而时间复杂度则是由于对半分而不是遍历的关系则是O(NlogN)

  

归并排序个人理解

上一篇:JavaScript(JS) Math.LN2


下一篇:基于Windows Server 2008 R2的Failover Cluster