Algorithm 基数排序的时间消耗
艾伦的书中有句话我不太明白: 例如,我们可以对计算机上可表示的所有整数(Algorithm 基数排序的时间消耗,algorithm,Algorithm,艾伦的书中有句话我不太明白: 例如,我们可以对计算机上可表示的所有整数(32位)进行基数排序,如果我们在2^11的桶大小上进行三次遍历。在这台计算机上,此算法将始终是O(N) 为什么O(N)?我的解释假设您了解基数排序 32位字长的计算机具有2^32-1(4294967295)可能的字长整数(从0x00到0xFF) bucket size为2^11表示每个bucket通过一个11位宽的字段(0b000 0000 0000到0b111 1111 1111)收集整数 我们可以将这些整数的位分成3部分
32位
)进行基数排序,如果我们在2^11
的桶大小上进行三次遍历。在这台计算机上,此算法将始终是O(N)
为什么
O(N)
?我的解释假设您了解基数排序
32位字长的计算机具有2^32-1
(4294967295
)可能的字长整数(从0x00
到0xFF
)
bucket size为2^11
表示每个bucket通过一个11位宽的字段(0b000 0000 0000到0b111 1111 1111)收集整数
我们可以将这些整数的位分成3部分,如下所示:
0b | 0000 0000 00 | 00 0000 0000 0 | 000 0000 0000
| ^section 3 ^ | ^ section 2 ^ | ^ section 1 ^
0b0000 0000 00XX XXXX XXXX XXXX XXXX XXXX
0b0000 0000 01XX XXXX XXXX XXXX XXXX XXXX
0b0000 0000 10XX XXXX XXXX XXXX XXXX XXXX
...
0b1111 1111 10XX XXXX XXXX XXXX XXXX XXXX
0b1111 1111 11XX XXXX XXXX XXXX XXXX XXXX
第1节是11个最不重要的位
第2节是下一个最不重要的11位
第3节是剩余的10位
部分1
位扣接。桶是这样的:
0bXXXX XXXX XXXX XXXX XXX X000 0000 0000
0bXXXX XXXX XXXX XXXX XXX X000 0000 0001
0bXXXX XXXX XXXX XXXX XXX X000 0000 0011
...
0bXXXX XXXX XXXX XXXX XXX X111 1111 1110
0bXXXX XXXX XXXX XXXX XXX X111 1111 1111
0bXXXX XXXX XX00 0000 0000 0XXX XXXX XXXX
0bXXXX XXXX XX00 0000 0000 1XXX XXXX XXXX
0bXXXX XXXX XX00 0000 0001 1XXX XXXX XXXX
...
0bXXXX XXXX XX11 1111 1110 1XXX XXXX XXXX
0bXXXX XXXX XX11 1111 1111 1XXX XXXX XXXX
X
s表示与此阶段无关的位。每个整数根据其节1
位放入这些2^11
桶中的一个。这是一个O(N)
操作。完成后,2^11
存储桶按从低到高的顺序迭代,元素被放入中间列表。现在,如果只查看元素的第1节
位,则此列表中的元素已排序
第二阶段
接下来,来自阶段1
中间列表的整数被其部分2
位扣住。桶是这样的:
0bXXXX XXXX XXXX XXXX XXX X000 0000 0000
0bXXXX XXXX XXXX XXXX XXX X000 0000 0001
0bXXXX XXXX XXXX XXXX XXX X000 0000 0011
...
0bXXXX XXXX XXXX XXXX XXX X111 1111 1110
0bXXXX XXXX XXXX XXXX XXX X111 1111 1111
0bXXXX XXXX XX00 0000 0000 0XXX XXXX XXXX
0bXXXX XXXX XX00 0000 0000 1XXX XXXX XXXX
0bXXXX XXXX XX00 0000 0001 1XXX XXXX XXXX
...
0bXXXX XXXX XX11 1111 1110 1XXX XXXX XXXX
0bXXXX XXXX XX11 1111 1111 1XXX XXXX XXXX
每个整数根据其第2节
位放入其中一个2^11
桶中。这是另一个O(N)
操作。一旦完成,2^11
存储桶按从低到高的顺序迭代,元素被放入一个新的中间列表中。如果只查看第1节
和第2节
位,则此列表中的元素现在已排序
第三阶段
接下来,来自阶段2
中间列表的整数被其部分3
位扣住。理论上,如果计算机有一个33位的word大小,我们可以使用所有2^11
存储桶,并在O(N)
中对所有可能的33位的整数进行排序。但出于我们的目的,本阶段实际上只需要2^10
存储桶,如下所示:
0b | 0000 0000 00 | 00 0000 0000 0 | 000 0000 0000
| ^section 3 ^ | ^ section 2 ^ | ^ section 1 ^
0b0000 0000 00XX XXXX XXXX XXXX XXXX XXXX
0b0000 0000 01XX XXXX XXXX XXXX XXXX XXXX
0b0000 0000 10XX XXXX XXXX XXXX XXXX XXXX
...
0b1111 1111 10XX XXXX XXXX XXXX XXXX XXXX
0b1111 1111 11XX XXXX XXXX XXXX XXXX XXXX
每个整数根据其第3节
位放入其中一个2^11
桶中。这是另一个O(N)
操作。完成后,2^10
存储桶按从低到高的顺序迭代,元素被放入一个新列表中。由于第1节
、第2节
和第3节
位都已计算完毕,因此此列表是最终的排序结果
总结
此过程花费了6个O(N)
过程:
通过第1节
从桶中收集
通过第2节
从桶中收集
通过第3节
从桶中收集
因此,总的来说,这个算法是O(N)
那么,你认为它应该是什么呢?当我们不知道你的误解可能是什么的时候,很难解释一些事情。我正在写一个解释,但需要一秒钟。这很简单。正确实现的基数排序在每次传递中每个已排序元素花费恒定的精力。如果您有N个元素,并且您通过表示输入的大小有限(这里您是说将有3个过程,因为上限(32/11)=3)来固定过程的数量,那么总时间是O(常数*3*N)=O(N)。