我很难理解存储桶排序的基本概念,我希望有人可以向我详细说明排序算法的作用以及它如何在O(N中完成所需的结果(排序内部容器) ) 时间。此外,由于这似乎相当快,其他排序算法(如冒泡,插入或选择)有哪些优势可以说服人们在桶排序中使用它们?
这是我在网上找到的算法的实现。如果有人可以在他们的解释中提到这一点,我将非常感激。
void binsort(std::vector<std::size_t>& A){
std::vector<std::vector<std::size_t>> B(MAX + 1);
for(std::size_t i = 0; i < SIZE; ++i){
B[A[i]].push_back(A[i]);
}
std::size_t current = 0;
for(std::size_t i = 0; i < MAX; ++i){
for(auto item : B[i]){
A[current++] = item;
}
}
}
感谢您的帮助。
答案 0 :(得分:4)
我会尝试解释这个具体的实现,这是你可能会看到的最简单的实现之一。不巧的是,输入域中也允许使用允许数字的严格限制(由值MAX
表示)。
假设我们有10个数字的集合。他们共享的一个属性是它们都在域[0..5]
中{ 3, 2, 2, 5, 1, 4, 0, 2, 5, 4 }
现在,我们创建一个桶的“列表”,其中每个桶代表来自域的值的集合; 不输入数组。我们的域允许6个可能的值,因此我们创建了六个桶(如果您没有注意到,则按“顺序”):
0: {}
1: {}
2: {}
3: {}
4: {}
5: {}
现在遍历输入列表,将每个值放入其存储桶中。从概念上讲,它在完成时看起来像这样:
0: {0}
1: {1}
2: {2,2,2}
3: {3}
4: {4,4}
5: {5,5}
现在,只需遍历我们的桶列表,然后将每个桶中的内容转储回原始容器中,替换那里的任何项目。
{ 0, 1, 2, 2, 2, 3, 4, 4, 5, 5}
似乎很简单,是吗?那么为什么不是每个人都这样做呢?好吧,考虑我们扩大问题。除了MAX
6个可能的值之外,我们将'{''限制为1048576
(2 20 ,以防您想知道),但保留数字项目分类为10 。
现在,给出以下列表:
{ 3, 2, 2, 1048576, 1, 4, 0, 2, 5, 4 }
我们的“桶”列表如下所示:
0: {0}
1: {1}
2: {2,2,2}
3: {3}
4: {4,4}
5: {5}
6: {}
7: {}
.....
1048575: {}
1048576: {1048576}
是的,超过一百万个桶来排序十个数字,所有这些都是因为这是我们问题域中允许的最大值。显然,这对于大型MAX
天花板来说是不可行的。将输入范围细分为可管理的集合将是一个可行的解决方案(实际上,基本上是基数排序的工作方式。
要回答你的最后一组问题,很明显,如果你有一个相当小的输入域,你很难在排序速度上击败它。例如,如果我们有一千个数字的集合,所有都在[0..9]
,那么这将是咆哮 - 快速。添加几个数量级,它根本就没有比较。但是,您支付的 重价格的价格是受限制的输入域。随着域大小的增加,您必须从桶分裂算法的角度来看待它,并且当您这样做时,您开始向O(NlogN)的路径。鉴于此,有大量算法(堆排序,合并排序,快速排序等),并且有一些值得考虑的警告。
一个显而易见的“胜利”的地方:假设您必须对一百万个8位字符进行排序(根据定义[0..255]
中的值),您将找不到更快的算法来执行此操作。域名定义明确,非常易于管理,如果使用了适当的“桶”表(字面意思是计数器表),我看不出它被击败了。
答案 1 :(得分:0)
这是Wikipedia提供的解释。我希望这就足够了。
Bucket sort或bin sort是一种排序算法 将数组划分为多个存储区。然后是每个桶 单独排序,使用不同的排序算法,或者 递归地应用桶排序算法。它是一个 分布排序,并且是最基本排序的表亲 重要的数字味道。 Bucket sort是一个概括 鸽笼排序。由于桶排序不是比较排序,因此Ω(n log n)下限不适用。计算复杂性 估计涉及桶的数量。
Bucket sort的工作原理如下:
答案 2 :(得分:0)
给出的解释非常酷。那么,如果我们有负数,我们如何处理这种情况呢?一种方法是为负数保留一个单独的桶列表。
想象一下这个数据集:{ - 5,-6,5,3,6,-4}
所以这里我们的&#34;桶列表&#34;如下:
清单1:
0: {0}
1: {0}
2: {0}
3: {1}
4: {0}
5: {1}
6: {1}
Bucket list 2:
-1: {0}
-2: {0}
-3: {0}
-4: {1}
-5: {1}
-6: {1}
因此,如果我们的案例只涉及整数,那么我们的存储桶列表甚至不必包含其他列表。它们可以只是列表。
答案 3 :(得分:0)
要处理负数的情况,您可以选择最小的负数,并将该数字添加到数组中的每个元素。
{-5,-6,5,3,6,-4}
具有最小元素-6
。将绝对值-6添加到数组中。
数组现在为{1,0,11,9,12,2}
然后使用存储桶数组对其进行排序,该数组变为{0,1,2,9,11,12}
,并为每个数据库添加-6
最终结果{-6,-5,-4,3,5,6}
。<?php
$min = 100000; // just initialize min with large value.
// these values can be hard coded, from JSON, html form, or database
// it is just written for illustration
$arr = array(
'Mashed Potatoes' => 2,
'Turkey' => 4,
'Pumpkin Pie'=> 4,
'Stuffing'=> 3
);
// we loop through each element of the above array and,
// compare its value to the min.
foreach($arr as $value){
if( $value < $min){
// If the value is less that min. then we store value into min
$min = $value;
}
}
echo 'You can have ' . $min . ' Thanksgiving dinners';
?>
。性能方面,这是可以的,因为减法并且向阵列添加最低范围是O(N)。