算法稳定性,时间复杂度,空间复杂度等算法基础知识: 经典算法----基础知识
冒泡排序: 基础算法----冒泡排序
选择排序: 基础算法----选择排序
插入排序: 基础算法----插入排序
快速排序: 基础算法----快速排序
希尔排序: 基础算法----希尔排序
归并排序: 基础算法----归并排序
计数排序: 基础算法----计数排序
桶排序: 基础算法----桶排序
基数排序: 基础算法----基数排序
堆排序: 基础算法----堆排序
一 算法简介
桶排序并不是基于比较的排序
桶排序是将序列分为多个区域,即多个桶,再对每个桶中元素进行排序,最后再把每个桶的元素依次放到序列中,排序完成
桶排序的两个注意点:
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∗(log2n−log2m))
当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
}