基础算法----桶排序(Bucket sort)


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

一 算法简介

桶排序并不是基于比较的排序

桶排序是将序列分为多个区域,即多个桶,再对每个桶中元素进行排序,最后再把每个桶的元素依次放到序列中,排序完成


桶排序的两个注意点:
1) 桶的个数:没有一个明确的划分桶个数的规则,桶的个数需要根据待排序集合的元素分布特性进行选择
2) 排序算法:对各个桶中元素进行排序时,可以选择合适的排序算法,桶排序算法的复杂度和稳定性根据选择的排序算法不同而不同

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

一) 时间复杂度

把元素分配到对应的桶的时间复杂度: T ( n ) = O ( n ) T(n) = O(n) T(n)=O(n)
对桶中元素进行排序并放入序列中的时间复杂度: T ( n ) = O ( m ∗ ( n m ) ∗ l o g 2 ( n m ) ) T(n) = O(m*(\frac{n}{m})*log_2(\frac{n}{m})) T(n)=O(m(mn)log2(mn))
其中:
n:序列中元素个数
m:桶的个数
n/m:每个桶中的元素个数
log2(n/m):对每个桶排序的时间复杂度,不一定是这个值,只是基于比较排序算法的最好的时间复杂度为nlog2n

所以总的时间复杂度为
T ( n ) = O ( n ) + O ( m ∗ ( n m ) ∗ l o g 2 ( n m ) )      = O ( n + n ∗ ( l o g 2 n − l o g 2 m ) ) T(n) = O(n)+O(m*(\frac{n}{m})*log_2(\frac{n}{m}))\\ \space\space\space\space= O(n+n*(log_2n-log_2m)) T(n)=O(n)+O(m(mn)log2(mn))    =O(n+n(log2nlog2m))

当n=m,即每个桶只有一个元素时,此时有最好时间复杂度,时间复杂度为O(n)
当m=1,即只有一个桶时,时间复杂度为O(n+nlog2n)

桶排序的时间复杂度为T(n) = O(n+c),其中c=n(log2n-log2m)

二) 空间复杂度

桶排序需要申请额外的空间作为桶来存储元素,如果桶的数量非常多,则需要花费更大的空间代价

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

其中:
n:序列中元素个数
m:桶的个数

三 算法稳定性

严格意义上,桶排序的稳定性取决于排序使用的算法
但总体上可以认为桶排序是一种稳定的排序算法

四 实现

一) 步骤

1) 将待排序序列划分为n个大小相等的子区间(桶),即划分为n个桶
2) 将元素放入对应的桶中
3) 使用排序算法对每个桶中的元素进行排序,排序后把每个桶的元素依次放到待排序序列中

二) 代码实现

每个桶储存值的区间为10,排序算法使用插入排序的桶排序实现如下:

func BucketSort(arr []int) {

	if len(arr) <= 1 {
		return
	}

	//获取最大值和最小值
	maxValue, minValue := arr[0], arr[0]
	for i := 1; i < len(arr); i++ {
		if arr[i] > maxValue {
			maxValue = arr[i]
		}
		if arr[i] < minValue {
			minValue = arr[i]
		}
	}

	//每个桶存储值的区间
	bucketRange := 10
	//计算桶的个数
	bucketCount := getBucketCount(maxValue, minValue, bucketRange)
	//元素分配到对应的桶
	bucketArr := make([][]int, bucketCount)
	for _, val := range arr {
		index := (val - minValue) / bucketRange
		bucketArr[index] = append(bucketArr[index], val)
	}

	//重新排序
	for i, j := 0, 0; i < len(bucketArr); i++ {
		insertionSort(bucketArr[i])
		for _, val := range bucketArr[i] {
			arr[j] = val
			j++
		}
	}

	return
}

func getBucketCount(max, min, bucketRange int) int {

	bucketCount := (max - min) / bucketRange
	devi := (max - min) % bucketRange
	if devi != 0 {
		bucketCount++
	}

	return bucketCount
}

func insertionSort(arr []int) {

	if len(arr) <= 1 {
		return
	}

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

	return
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值