倒霉的菜鸟

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

如果有这样一个数组,整体是无序的, 但是前半部分和后半部分分别是有序的

 

 

 现在我们定义一个方法对它进行排序:

 1 /**
 2      * array 如: intArrayOf(1,2,5,9,3,4,10,11)
 3      * left = 0,
 4      * middle = 4,
 5      * right = 7
 6      */
 7     fun merge(array: IntArray, left: Int, middle: Int, right: Int){
 8         //我们先把数组按照Middle分割成两个数组
 9         val leftArraySize = middle-left
10         val rightArraySize = right-middle+1
11         //定义两个数组 (这就是归并排序消耗空间的地方)
12         val leftArray = IntArray(leftArraySize)
13         val rightArray = IntArray(rightArraySize)
14         //把原数组的元素copy到新数组
15         for (i in left until middle) {
16             leftArray[i - left] = array[i]
17         }
18         for (i in middle..right) {
19             rightArray[i - middle] = array[i]
20         }
21 
22         //合并
23         var i=0
24         var j=0
25         var k=left
26        while (i < leftArraySize && j < rightArraySize){
27            //如果左边第一个数比右边第一个数小
28            if (leftArray[i] < rightArray[j]){
29                array[k] = leftArray[i]
30                k++
31                i++
32            } else {
33                array[k] = rightArray[j]
34                k++
35                j++
36            }
37        }
38         //上面while会在某个数组元素取完之后执行完毕
39         //如果 i 小于 leftArray.size, 说明左边数组中有元素没取完
40         while (i<leftArraySize){
41             //那么就把左边数组中的元素放到array中
42             array[k++] = leftArray[i++]
43         }
44         //如果  j小于 rightArray.size, 说明右边数组中有元素没取完
45         while (j<rightArraySize){
46             //那么就把右边数组中的元素放到array中
47             array[k++] = rightArray[j++]
48         }
49     }

定义归并排序的方法

 1 fun mergeSort(array: IntArray, start: Int, end: Int){
 2         if (start==end){
 3             return
 4         }else{
 5             //取中间值
 6             val middle = (start+end)/2
 7             //对左边归并排序
 8             mergeSort(array, start, middle)
 9             //右边归并排序
10             mergeSort(array, middle+1, end)
11             //左右合并
12             merge(array, start, middle+1, end)
13 
14         }
15     }

这里不是很好理解

 

 要理解这段代码需要先理解递归进栈出栈的顺序

结合上图, 代码执行到mergeSort(array, left, mid)的时候,递归调用自身,同时后面的两行代码进栈

递归调用又得到Mid为之前的一半, 再递归调用自身, 同时后面两行进栈

直到left==right,第一层递归调用完毕。代码按照先进后出的原则出栈,可以想象最先被执行到的是6和3的merge, 然后才是3,6 和1,9的合并, 最后执行1,3,6,9,和2,4,5,7的合并。

所以不难理解,归并排序的时间复杂度也是n*log2N

 

其实就是使用递归将数组拆分成一个一个的元素, 然后从下往上两两合并

 

posted on 2021-10-08 20:55  倒霉的菜鸟  阅读(86)  评论(0编辑  收藏  举报