如果有这样一个数组,整体是无序的, 但是前半部分和后半部分分别是有序的
现在我们定义一个方法对它进行排序:
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
其实就是使用递归将数组拆分成一个一个的元素, 然后从下往上两两合并