归并排序
最近受了不小的打击,又开始学习数据结构与算法了,不知道能坚持多久,写博客只为学习记录。
一、归并排序思想:归并排序用到了分治思想,假设要排序一个数组,先把这个数组从中间分成前后两个部分,然后对前后两个子数组分别排序,再将排序好的两个子数字合并再一起,整个数组就有序了。这种分治的问题可以用递归来解决。
二、递归实现分析:递归代码编写有两个重要的步骤:1.推到递推公式 2.递归结束条件,接下来就可以将递推公式翻译成代码了,根据数组划分的分析,递归公式可以表示为:mergeSort(a...b) = merge( mergeSort(a...mid) , mergeSort(mid+1, b),这个mid是数组的中间位置,结束条件为a>=b,不需要再分解了。合并有序子数组的时候,需要申请原数组大小的临时空间。
三、代码实现:用go语言实现归并排序代码
1 func sortArray(nums []int) []int { 2 mergeSort(nums, 0, len(nums) - 1) 3 return nums 4 } 5 6 //想用归并排序,递归实现 7 func mergeSort(nums []int, i int, j int) { 8 //递归终止条件 9 if i >= j { 10 return 11 } 12 13 //将当前序列划分为两个子序列 14 q := (i+j)/2 15 //递归的排序左右两个子序列 16 mergeSort(nums, i, q) 17 mergeSort(nums, q+1, j) 18 19 //需要将排序好的数据合并 20 merge(nums, i, q, j) 21 } 22 23 func merge(nums []int, start int, mid int, end int) { 24 //申请一个合并两个子序列需要的临时数组 25 var numTemp []int 26 var index1, index2 = start, mid + 1 27 for index1 <= mid && index2 <= end { 28 //逐个对比两个子序列的值 29 if nums[index1] <= nums[index2] { 30 numTemp = append(numTemp, nums[index1]) 31 index1++ 32 } else { 33 numTemp = append(numTemp, nums[index2]) 34 index2++ 35 } 36 } 37 38 //某一个子序列已经遍历完了,看看到底是哪个没完,直接把数据放到临时空间就好了 39 if index1 <= mid { 40 numTemp = append(numTemp, nums[index1: mid+1]...) 41 } 42 if index2 < end { 43 numTemp = append(numTemp, nums[index2: end+1]...) 44 } 45 46 for index, data := range numTemp { 47 nums[start + index] = data 48 } 49 }
四、代码调试:代码写完跑的时候,发现Panic了,然后参考了网上的实现,才发现go的切片操作a[ i : j ] 是不包含j元素的,改了后就可以了。
学习参考:golang归并排序 - Go语言中文网 - Golang中文社区 (studygolang.com)
极客时间《数据结构与算法之美》