基础算法----归并排序(Merge Sort)


算法稳定性,时间复杂度,空间复杂度等算法基础知识经典算法----基础知识
冒泡排序基础算法----冒泡排序
选择排序基础算法----选择排序
插入排序基础算法----插入排序
快速排序基础算法----快速排序
希尔排序基础算法----希尔排序
归并排序基础算法----归并排序
计数排序基础算法----计数排序
桶排序基础算法----桶排序
基数排序基础算法----基数排序
堆排序基础算法----堆排序

一 算法简介

归并排序将待排序序列分割成若干个子序列,递归分割子序列,直到不能分割,然后递归合并子序列(递归地使每个子序列有序,然后再把有序的子序列合并成一个有序的序列)

归并排序的速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列

归并排序是采用分治法(Divide and Conquer)的排序算法,比较占用内存,但却是一种效率高且稳定的算法

二 时间复杂度,空间复杂度

一) 时间复杂度

每次都将当前序列分割为长度接近的两个子序列,最好和最坏情况的时间复杂度都一样

假设每一次把原序列分成两部分:X1,X2
所以时间复杂度 T(n) = D(n) + T(X1) + T(X2)

T(n) = D(n) + 2T(n/2)
   = D(n) + 2D(n/2) + 4T(n/4)
   = D(n) + 2D(n/2) + 4D(n/4) + 8T(n/8)
   = D(n) + 2D(n/2) + … + 2kD(n/2k)

其中 D(n) = n -1, k = log2n
D(n) 表示每一次递归操作的比较次数,k表示经过log2n分割,即可得到长度为1的子序列

所以T(n) = n-1 + n-2 + … + n - 2k
     = nlog2n - 2n +1

平均时间复杂度为 T(n) = O(nlog2n)

二) 空间复杂度

空间复杂度为临时数组和递归时程序栈层数占用的空间总和:S(n) = n + log2n

空间复杂度为 S(n) = O(n)

三 算法稳定性

相同元素的相对位置不会由于归并发生变化,归并排序是一种稳定的排序算法

四 实现

一) 步骤

1) 将待排序序列分割成长度为 n/2 的子序列
2) 递归分割子序列,直到不能分割
3) 递归合并子序列

二) 过程图

使用 {40, 30, 50, 40, 20, 60, 10, 70} 演示从小到大的排序过程

归并排序----过程图

三) 代码实现

func MergeSort(arr []int) []int {

	if len(arr) <= 1 {
		return arr
	}
	n := len(arr) / 2
	return merge(MergeSort(arr[:n]), MergeSort(arr[n:]))
}


func merge(leftSubArr, rightSubArr []int) (res []int) {
	
	length := len(leftSubArr) + len(rightSubArr)
	res = make([]int, length)

	l, r := 0, 0
	for i := 0; i < length; i++ {
		//说明rightSubArr中存在比leftSubArr最后一个元素(最大元素)大的元素
		if l >= len(leftSubArr) {
			res[i] = rightSubArr[r]
			r++
		//说明leftSubArr中存在比rightSubArr最后一个元素(最大元素)大的元素
		} else if r >= len(rightSubArr) {
			res[i] = leftSubArr[l]
			l++
		} else if leftSubArr[l] < rightSubArr[r] {
			res[i] = leftSubArr[l]
			l++
		} else {
			res[i] = rightSubArr[r]
			r++
		}
	}

	return
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值