归并排序
思想:
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。 --百度百科
时间复杂度:O(nlogn)
稳定性:稳定
Go语言实现
分治规则
func mergeSort(arr []int,left int,right int){
if right > left{
mid := (left+right)/2
mergeSort(arr,left,mid) // 左边分治
mergeSort(arr,mid+1,right) // 右边分治
// 分治完则合并
merge(arr,left,mid,right)
}
}
合并规则
func merge(arr []int,left int,mid int,right int){
var temp = make([]int,len(arr)) // 开辟一个临时数组,存放合并之后的数组
var pointer1 = left // 左边的指针 指向左边数组的第一个元素
var pointer2 = mid+1 // 右边的指针 指向右边数组的第一个元素
var loc = left // 用于记录临时数组当前指针指向
for pointer1<=mid && pointer2<=right{ //一直遍历左右两个数组
if arr[pointer1] < arr[pointer2] { // 较小的元素先进入
temp[loc] = arr[pointer1]
pointer1++ // 左边数组指向下一位
}else{
temp[loc] = arr[pointer2]
pointer2++ // 右边数组指向下一位
}
loc++ // 插入一个元素后,临时数组位置指向下一位
}
// 虽然左右两边数组都已经插入到临时数组中,但左右两边尾部的元素依旧没有插入,因此,这里还需要再插入一次
for pointer1 <= mid { // 左边继续合并
temp[loc] = arr[pointer1]
loc++
pointer1++
}
for pointer2 <= right { // 右边继续合并
temp[loc] = arr[pointer2]
loc++
pointer2++
}
// 此时,并操作已经完成,现在需要把临时数组重新截取值
for i:=left;i<=right;i++{
arr[i]=temp[i]
}
}
//测试
func main() {
var data = []int{3, 5, 75, 34, 8, 31, 44, 76, 87, 25, 73, 11}
mergeSort(data, 0, len(data)-1)
fmt.Println(data) //[3 5 8 11 25 31 34 44 73 75 76 87]
}
总结
归并排序是分治思想的运用,其核心是将需要排序的数组按照一定规则分下去,分到无法再分的时候再对左右两边数组元素进行对比,再以小的排在前面大的排在后面(或大的排在前面小的排在后面)的方式合并成一个数组,实现有序