经典排序算法汇总(go实现)

163 阅读4分钟

0 大纲

基本算法的复杂度:

1 基本概念

稳定性

时间复杂度

**时间复杂度:**用来衡量随着算法规模的扩大,算法执行时间增长的快慢。

**常见时间复杂度:**O(1)<O(log n)<O(nlog n)<O(n^2)<O(n^3)<O(2^n)

长用计算方法:

  1. 单个循环直接关注循环次数
  2. 多个循环:内循环-乘法规则,外循环-加法规则

空间复杂度

**空间复杂度:**算法执行过程中所使用辅助空间的大小

**常见时间复杂度:**一般为O(1),O(logn),O(n)

2 冒泡排序

时间复杂度:O(n^2)——两个循环嵌套

空间复杂度:O(1)——基本操作在于交换两个数据

稳定性:稳定

//Mpsort 冒泡算法
func Mpsort(arr []int) {
	l := len(arr)
	for i := 0; i < l; i++ {
		for j := 0; j < l-i-1; j++ {
			if arr[j] > arr[j+1] {
				arr[j], arr[j+1] = arr[j+1], arr[j]
			}
		}
	}
}

3 快速排序

时间复杂度:O(nlogn)

空间复杂度:O(nlogn)——递归调用

稳定性:不稳定

//Ksort 快排
func Ksort(arr []int) {
	l := len(arr)
	if l < 2 {
		return
	}
	temp := arr[0]
	i, j := 0, l-1
	for i < j {
		for arr[j] > temp && i < j {
			j--
		}
		arr[i] = arr[j]
		for arr[i] < temp && i < j {
			i++
		}
		arr[j] = arr[i]
	}
	arr[i] = temp
	Ksort(arr[0:i])
	Ksort(arr[i+1 : l])
}

4 简单选择排序

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:不稳定

//Xzsort 选择排序
func Xzsort(arr []int) {
	l := len(arr)
	for i := 0; i < l-1; i++ {
		min := i
		for j := i + 1; j < l; j++ {
			if arr[j] < arr[min] {
				min = j
			}
		}
		if min != i {
			arr[i], arr[min] = arr[min], arr[i]
		}
	}
}

5 堆排序

时间复杂度:O(nlogn)

空间复杂度:O(1)

稳定性:不稳定

//Heapsort 堆排序
func Heapsort(arr []int) {
	//生成最小堆
	l := len(arr)
	for i := (l - 1) / 2; i >= 0; i-- {
		downadjust(arr, i, l-1)
	}
	//进行排序
	for i := l - 1; i > 0; i-- {
		arr[i], arr[0] = arr[0], arr[i]
		downadjust(arr, 0, i-1)
	}
}

//downadjust 向下调整
func downadjust(arr []int, root int, end int) {
	temp := arr[root]
	child := root*2 + 1
	for child <= end {
		if child+1 <= end && arr[child] < arr[child+1] {
			child = child + 1
		}
		if arr[child] < temp {
			break
		}
		arr[root] = arr[child]
		root = child
		child = 2*root + 1
	}
	arr[root] = temp
}

6 直接插入排序

时间复杂度:O(nlogn)

空间复杂度:O(1)

稳定性:不稳定

//Crsort 插入排序
func Crsort(arr []int) {
	l := len(arr)
	var temp int
	tag := 0
	for i := 1; i < l; i++ {
		tag = 0
		temp = arr[i]
		for j := i - 1; j >= 0; j-- {
			if temp > arr[j] {
				arr[j+1] = temp
				tag = 1
				break
			}
			arr[j+1] = arr[j]
		}
		if tag == 0 {
			arr[0] = temp
		}
	}
}

7 折半插入排序

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:稳定

//Zbcrsort 折半插入排序
func Zbcrsort(arr []int) {
	l := len(arr)
	var (
		temp int
		p    int
	)
	for i := 1; i < l; i++ {
		temp = arr[i]
		//找到插入位置p
		p = insertplace(arr, 0, i-1, i)
		//排序
		for j := i; j > p; j-- {
			arr[j] = arr[j-1]
		}
		arr[p] = temp
	}
}

//insertplace 检索插入点
func insertplace(arr []int, start int, end int, current int) int {
	if start >= end {
		if arr[start] < arr[current] {
			return current
		}
		return start
	}

	mid := start + (end-start)/2
	if arr[mid] > arr[current] {
		return insertplace(arr, 0, mid, current)
	}
	return insertplace(arr, mid+1, end, current)
}

8 希尔排序

时间复杂度:O(n^1.3)

空间复杂度:O(1)

稳定性:不稳定

//Xesort 希尔排序
func Xesort(arr []int) {
	l := len(arr)
	step := l / 2
	for step > 0 {
		for i := 0; i < l; i++ {
			j := i
			for j-step >= 0 && arr[j-step] > arr[j] {
				arr[j-step], arr[j] = arr[j], arr[j-step]
				j -= step
			}
		}
		step /= 2
	}
}

9 归并排序

时间复杂度:O(nlogn)

空间复杂度:O(n)

稳定性:稳定

//Gbsort 归并排序
func Gbsort(arr []int) []int {
	l := len(arr)
	if l < 2 {
		return arr
	}
	mid := l / 2
	left := Gbsort(arr[0:mid])
	right := Gbsort(arr[mid:l])
	ans := merge2(left, right)
	return ans
}

//merge2 合并
func merge2(left []int, right []int) []int {
	ll, lr := len(left), len(right)
	i, j := 0, 0
	ans := []int{}
	for i < ll && j < lr {
		if left[i] < right[j] {
			ans = append(ans, left[i])
			i++
		} else {
			ans = append(ans, right[j])
			j++
		}
	}
	ans = append(ans, left[i:]...)
	ans = append(ans, right[j:]...)
	return ans
}

10 计数排序

时间复杂度:O(n+k)

空间复杂度:O(k)

稳定性:稳定

//Jssort 计数排序
func Jssort(arr []int, maxvalue int) {
	//定义一个最大值+1长的数组,用于分类存放
	bucket := make([]int, maxvalue+1)
	l := len(arr)
	sortedindex := 0
	//存放到相应位置上
	for i := 0; i < l; i++ {
		bucket[arr[i]] = bucket[arr[i]] + 1
	}
	//依次取出放回原数组
	for i := 0; i < maxvalue+1; i++ {
		for bucket[i] > 0 {
			arr[sortedindex] = i //注意这里放的是i
			sortedindex++
			bucket[i]--
		}
	}
}