排序算法-归并排序详解

        归并排序采用分治的思想,采用先拆分再合并的方式,得到完全有序的序列。归并排序属于稳定排序。

        时空复杂度

                归并排序的时间复杂度,在最好、最坏以及平均复杂度都是O(nlog2n),在每一层上最多有n个元素,也就是说每一层最多进行n次比较,递归树的层数为log2n,所以合起来就是O(nlog2n);

        归并排序的空间复杂度为O(1)

        算法思想

        归并排序主要包括两部分:拆分+合并(排序),首先介绍拆分,在一个数组中,取该数组最左和最右两端的下标相加然后除以2,得到一个中间下标值,以这个下标值为拆分点,对当前数组进行拆分,然后再对拆分后的数组分别再进行拆分,直到拆分的数组元素都只有一个为止,下图是拆分的具体过程:

        从原始数组开始,左下标为0,右下标为8,所以中间拆分下标为4,拆成了两个数组;然后再分别对这两个数组进行拆分,左边数组左下标为0,右下标为4,中间拆分下标为2,所以左边数组又拆成了两个数组;右边数组同理;直到最后将所有数组拆分成一个元素停止;这样拆分过程就完成了,接下来进行合并排序。

        如上图所示,当拆分完之后,我们将拆分之后的元素每两两去合并排序,从9和5开始,此时在最后一层,将9和5进行比较,5比9小所以将5写到临时数组前面存放,然后将9放到5后面,此时原来拆分的2个元素的数组合并完成了,这时候合并之后数组都是有序的;

        再往上一层,此时需要合并的数组有{5,9}和{2};{7}和{12};{3}和{4}以及{1}和{11};先合并{5,9}和{2},将这两个数组进行排序,先将左边数组的5与右边数组的2进行比较,2比5小,所以先将2写入到临时数组最左边,然后再用5与右边数组比较,发现右边数组没有元素了,此时则将左边数组所有的元素写入临时数组中,这时,临时数组中就都是有序的,得到{2,5,9};其他数组同理,最后得到{7,12}、{3,4}和{1,11};

        然后再回到上一层,将{2,5,9}与{7,12}进行合并,先从左边数组开始,将最小的元素与右边数组最小的元素进行依次比较,将2写入到临时数组,然后再从左边数组下一个元素与右边最小元素比较,5比7小,将5继续写入临时数组,然后9与7进行比较,将7写入临时数组,在将9与12进行比较,将9写入临时数组,最后将12写入临时数组,剩下的数组也按照此算法进行合并,最终回到第一层后,临时数组会是一个有序的数组,最后将临时数组替换原数组就完成了归并排序。

代码实现

package mergesort

import "fmt"

func merge(arr []int, temp []int, left, mid, right int) {
	l_pos := left
	r_pos := mid + 1
	pos := left
	//将两个数组中最小的先放到临时数组中
	for l_pos <= mid && r_pos <= right {
		if arr[l_pos] <= arr[r_pos] {
			temp[pos] = arr[l_pos]
			pos++
			l_pos++
		} else {
			temp[pos] = arr[r_pos]
			pos++
			r_pos++
		}
	}
	//如果右边数组遍历完了,但是左边数组还有剩余元素,则将剩余元素拷贝到临时数组中
	for l_pos <= mid {
		temp[pos] = arr[l_pos]
		pos++
		l_pos++
	}
	//如果左边数组遍历完了,但是右边数组还有剩余元素,则将剩余元素拷贝到临时数组中
	for r_pos <= right {
		temp[pos] = arr[r_pos]
		pos++
		r_pos++
	}
	//最后将临时数组中的所有元素都更新到原数组中取
	for left <= right {
		arr[left] = temp[left]
		left++
	}
}

func mSort(arr []int, temp []int, left, right int) {
	if left < right {
		mid := (left + right) / 2
		//将数组不停的拆分为两部分,直到数组中的元素只有一个
		mSort(arr, temp, left, mid)
		mSort(arr, temp, mid+1, right)
		//开始一一对拆分的数组进行合并
		merge(arr, temp, left, mid, right)
	}
}

func mergeSort(arr []int) {
	tmpArr := make([]int, len(arr))
	mSort(arr, tmpArr, 0, len(arr)-1)
}

func main() {
	arr := []int{9, 5, 2, 7, 12, 4, 3, 1, 11}
	fmt.Println("arr:", arr)
	mergeSort(arr)
	fmt.Println("sort:", arr)
}
输出:
arr: [9 5 2 7 12 4 3 1 11]
sort: [1 2 3 4 5 7 9 11 12]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值