排序算法


/*冒泡排序:
* 时间复杂度O(n^2)
* 空间复杂度O(1)
* 稳定
 */
func bubbleSort(arr []int) []int {

	if len(arr) <= 0 {
		return arr
	}

	for i := 0; i < len(arr)-1; i++ {
		for j := 0; j < len(arr)-1-i; j++ {
			if arr[j] > arr[j+1] {
				tmp := arr[j]
				arr[j] = arr[j+1]
				arr[j+1] = tmp
			}
		}
	}

	return arr
}

/*选择排序:
* 时间复杂度O(n^2)
* 空间复杂度O(1)
* 不稳定
 */
func selectSort(arr []int) []int {

	if len(arr) <= 0 {
		return arr
	}

	for i := 0; i < len(arr)-1; i++ {
		minIndex := i
		for j := i + 1; j < len(arr); j++ {
			if arr[j] < arr[minIndex] {
				minIndex = j
			}
		}

		tmp := arr[i]
		arr[i] = arr[minIndex]
		arr[minIndex] = tmp
	}

	return arr
}

/*直接插入排序:
* 时间复杂度O(n^2)
* 空间复杂度O(1)
* 稳定
 */
func insertSort(arr []int) []int {

	for i := 1; i < len(arr); i++ {
		tmp := arr[i]
		j := i
		for ; j > 0; j-- {
			if tmp < arr[j-1] {
				arr[j] = arr[j-1]
			} else {
				break
			}
		}
		arr[j] = tmp
	}

	return arr
}

/*希尔排序:
* 时间复杂度O(n^1.3)
* 空间复杂度O(1)
* 不稳定
 */
func shellSort(arr []int) []int {

	for k := len(arr) / 2; k > 0; k = k / 2 {

		for i := k; i < len(arr); i++ {
			tmp := arr[i]
			j := i

			for ; j >= k; j -= k {
				if tmp < arr[j-k] {
					arr[j] = arr[j-k]
				} else {
					break
				}
			}

			arr[j] = tmp
		}
	}

	return arr
}

/*归并排序:
* 时间复杂度O(NlogN)
* 空间复杂度O(n)
* 稳定
 */
func mergeSort(arr []int) []int {

	length := len(arr)
	if length < 2 {
		return arr
	}

	mid := length / 2
	return merge(mergeSort(arr[0:mid]), mergeSort(arr[mid:]))
}

func merge(left, right []int) []int {

	lCount := len(left)
	rCount := len(right)

	arr := make([]int, 0)
	i := 0
	j := 0

	for i < lCount && j < rCount {
		if left[i] <= right[j] {
			arr = append(arr, left[i])
			i++
		} else {
			arr = append(arr, right[j])
			j++
		}
	}

	arr = append(arr, left[i:]...)
	arr = append(arr, right[j:]...)
	return arr
}

/*快速排序: 冒泡的升级版(减少了总交换次数)
* 时间复杂度O(NlogN)
* 空间复杂度O(logN)
* 不稳定
 */

func quickSort(arr []int) {

	qSort(arr, 0, len(arr)-1)
}

func qSort(arr []int, low, high int) {

	if low < high {
		p := partitionVal(arr, low, high)
		qSort(arr, low, p-1)
		qSort(arr, p+1, high)
	}
}

func partitionVal(arr []int, low, high int) int {

	tmp := arr[low]

	for low < high {

		for low < high && arr[high] >= tmp {
			high--
		}

		val := arr[low]
		arr[low] = arr[high]
		arr[high] = val

		for low < high && arr[low] < tmp {
			low++
		}

		val = arr[low]
		arr[low] = arr[high]
		arr[high] = val

	}

	return low
}

/*堆排序:选择排序的升级版(把每次比较的结果存下来再做相应调整)
* 不适合待排序序列个数较少的情况
* 时间复杂度O(NlogN)
* 空间复杂度O(1)
* 不稳定
 */
func heapSort(arr []int) {
	//二叉树的最后一个有孩子的节点的下标是n/2-1,
	//从右往左,从下往上将根节点及其子树调整大根堆

	for i := len(arr)/2 - 1; i >= 0; i-- {
		heapAdjust(arr, i, len(arr))
	}

	//遍历每次都将根节点和未交换过的末尾节点交换,再构造大根堆,重复直到所有元素都有序

	length := len(arr)
	for i := length - 1; i >= 0; i-- {
		tmp := arr[0]
		arr[0] = arr[i]
		arr[i] = tmp
		heapAdjust(arr, 0, i)
	}
}

func heapAdjust(arr []int, low, high int) {

	i := low
	tmp := arr[low]

	for j := 2*i + 1; j < high; j = j*2 + 1 {

		if j < high-1 && arr[j] < arr[j+1] { //可能没有右孩子
			j++
		}

		if arr[j] <= tmp { //如果根已经是最大的就不需要调整了,循环结束
			break
		}

		arr[i] = arr[j]
		i = j
	}

	arr[i] = tmp
}

/*计数排序: 适合当maxValue不是很大并且序列比较集中时
* 时间复杂度O(n)
* 空间复杂度O(n)
* 稳定
 */

func countSort(arr []int, maxValue int) {

	bucket := make([]int, maxValue+1)

	for i := 0; i < len(arr); i++ {
		bucket[arr[i]]++
	}

	idx := 0
	for j := 0; j < len(bucket); j++ {

		for bucket[j] > 0 {
			arr[idx] = j
			idx++
			bucket[j]--
		}
	}
}


/* 桶排序:计数排序升级版
* 数据均匀分布在各个桶中排序最快,数据被分在同一个桶中排序最慢
* 时间复杂度O(n)
* 空间复杂度O(n)
* 稳定
 */

func bucketSort(arr []int, bucketCount int) {

	maxVal := math.MinInt64
	for i := 0; i < len(arr); i++ {
		if arr[i] > maxVal {
			maxVal = arr[i]
		}
	}

	buckets := make([][]int, bucketCount)

	space := maxVal / (bucketCount - 1)

	for i := 0; i < len(arr); i++ {
		idx := arr[i] / space
		buckets[idx] = append(buckets[idx], arr[i])
	}

	pos := 0
	for i := 0; i < bucketCount; i++ {
		bucketLen := len(buckets[i])
		if bucketLen <= 0 {
			continue
		}

		insertSort(buckets[i])
		for k := 0; k < bucketLen; k++ {
			arr[pos] = buckets[i][k]
			pos++
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值