在帮助学生上课时,我实施了双轴快速排序算法来准备课程并引起了兴趣。运行一些统计数据,然后解决最坏情况,然后再次运行 stats,再次解决下一个最坏情况,重复这个过程几次,得到的代码不超过 80 行简单直接的 Python 代码(有点少于弗拉基米尔的代码)。新颖的部分是如何结合一些非常简单但有效的后处理来构建 3 个分区。现在我需要一些关于如何正确测试和统计数据的帮助。
特别是关于如何计算交换:大多数交换只执行两个分配而不是三个。那么我必须将它们视为完全交换,还是仅将它们视为“2/3”交换是否公平?
将每个交换都计算为1
,Cn
inCn * N * log2(N)
大约0.48
在短列表(<100 个元素)和数百万0.55
个元素的较长列表中。这只是Vladimir Yaroslavskiy计算的理论最小值。
相反,计算较轻的交换2/3
,所需交换的数量几乎与任何列表大小相等,并且约为0.36
(stdev around 0.015
)。
对于200 万条记录的列表,Cn
比较次数平均约为1.38(来自 2*N*ln(N)),而对于较短的列表(即1024 个元素)则更低,约为1.3
1.21
这是针对具有100% 唯一编号并使用 Python随机排序random.shuffle()
的列表。
所以我的问题是:
这样计算较轻的掉期是否可以,结果是否确实有希望?
另外有趣的是:
- 列表中的相等元素越多,排序越快。
Cn
是0.03
和0.1
分别用于交换和比较所有相等元素的200 万个列表。 Cn
对于排序和反向排序的列表对于所有大小几乎都是相同的:对于交换(用 计数)0.3
和比较。1
2/3
我将很快发布一个包含更多统计信息的列表,其中包括最大堆栈深度、除交换和比较之外的递归调用数。还有其他我应该计算的东西吗?
此外,是否有一些“标准”测试套件包含各种情况的文件(等于、部分排序等),可以用来测试排序算法,并使结果与其他排序算法具有可比性。
5 月 5 日添加:我改进了算法,特别是针对排序列表。这是每个运行 20 次的结果。这是好结果吗?
New statistics:
Random.shuffle(), unique number
Length Swaps/Nlog2(N) Comparisons/Nlog2(N) Maximum Stack/log2(N)
16 0.367 0.922 0.250
64 0.360 1.072 0.500
256 0.342 1.122 0.625
1024 0.358 1.156 0.800
4096 0.359 1.199 0.917
16384 0.359 1.244 1.071
65536 0.360 1.244 1.125
262144 0.360 1.269 1.167
1048576 0.362 1.275 1.200
Sorted, unique numbers
Length Swaps/Nlog2(N) Comparisons/Nlog2(N) Maximum Stack/log2(N)
16 0.172 0.531 0.250
64 0.117 0.586 0.333
256 0.087 0.609 0.375
1024 0.075 0.740 0.500
4096 0.060 0.732 0.500
16384 0.051 0.726 0.500
65536 0.044 0.722 0.500
262144 0.041 0.781 0.556
1048576 0.036 0.774 0.550
2097152 0.035 0.780 0.571
Reversed order, unique numbers
Length Swaps/Nlog2(N) Comparisons/Nlog2(N) Maximum Stack/log2(N)
16 0.344 0.828 0.250
64 0.279 0.812 0.333
256 0.234 0.788 0.375
1024 0.210 0.858 0.500
4096 0.190 0.865 0.500
16384 0.172 0.855 0.500
65536 0.158 0.846 0.500
262144 0.153 0.900 0.556
1048576 0.143 0.892 0.550
2097152 0.140 0.895 0.571