这是我很久以前遇到的问题。 我想我可能会问你的想法。 假设我有一个非常小的数字列表(整数),4或8个元素,需要快速排序。 什么是最好的方法/算法?
我的方法是使用max / min函数(10个函数对4个数字进行排序,没有分支,iirc)。
// s(i,j) == max(i,j), min(i,j)
i,j = s(i,j)
k,l = s(k,l)
i,k = s(i,k) // i on top
j,l = s(j,l) // l on bottom
j,k = s(j,k)
我想我的问题更多地与实现有关,而不是算法的类型。
此时它有点依赖硬件,所以让我们假设带有SSE3的Intel 64位处理器。
由于
答案 0 :(得分:34)
对于像这样的小型数组,您应该考虑sorting networks。正如您在该页面上看到的那样,插入排序可以表示为排序网络。但是,如果您事先知道阵列的大小,则可以设计出最佳网络。看一下this site,它可以帮助您找到给定大小的阵列的最佳排序网络(尽管最优化只能保证最大16个,我相信)。比较器甚至可以在可以并行完成的操作中组合在一起。比较器基本上与你的s(x,y)函数相同,但如果你真的希望它快,你不应该使用min和max,因为那时你需要进行两倍的必要比较。 / p>
如果您需要这种排序算法来处理各种各样的大小,那么您应该像其他人建议的那样使用插入排序。
答案 1 :(得分:7)
我看到你已经有了一个使用5次比较的解决方案(假设s(i,j)比较两个数字一次,然后交换它们或不交换)。如果你坚持基于比较的排序,那么你不能用少于5次的比较来做到这一点。
这可以证明,因为有4个! = 24种可能的方式来订购4个号码。每次比较只能将可能性减半,因此通过4次比较,您只能区分2 ^ 4 = 16种可能的排序。
答案 2 :(得分:7)
要对少量数字进行排序,您需要一个简单的算法,因为复杂性会增加更多开销。
对四个项目进行排序的最有效方法是将排序算法解析为线性比较,从而消除所有开销:
function sort(i,j,k,l) {
if (i < j) {
if (j < k) {
if (k < l) return [i,j,k,l];
if (j < l) return [i,j,l,k];
if (i < l) return [i,l,j,k];
return [l,i,j,k];
} else if (i < k) {
if (j < l) return [i,k,j,l];
if (k < l) return [i,k,l,j];
if (i < l) return [i,l,k,j];
return [l,i,k,j];
} else {
if (j < l) return [k,i,j,l];
if (i < l) return [k,i,l,j];
if (k < l) return [k,l,i,j];
return [l,k,i,j];
}
} else {
if (i < k) {
if (k < l) return [j,i,k,l];
if (i < l) return [j,i,l,k];
if (j < l) return [j,l,i,k];
return [l,j,i,k];
} else if (j < k) {
if (i < l) return [j,k,i,l];
if (k < l) return [j,k,l,i];
if (j < l) return [j,l,k,i];
return [l,j,k,i];
} else {
if (i < l) return [k,j,i,l];
if (j < l) return [k,j,l,i];
if (k < l) return [k,l,j,i];
return [l,k,j,i];
}
}
}
但是,对于您添加的每个额外项目,代码会增长很多。添加第五项使代码大约大四倍。八个项目大约有30000行,所以虽然它仍然是效率最高的,但是代码很多,而且你必须编写一个程序来编写代码以使其正确。
答案 3 :(得分:4)
插入排序被认为是小型阵列的最佳选择。见Fast stable sort for small arrays (under 32 or 64 elements)
答案 4 :(得分:3)
对于这么小的数据集,您希望算法尽可能简单。更有可能的是,基本的Insertion Sort会做到你想要的。
需要了解更多关于它运行的系统,你需要做多少次这样的事情等等......但是小规模的一般规则是保持简单。快攻等都没有用。
答案 5 :(得分:3)
排序网络可以很容易地在SIMD中实现,尽管它在N = 16附近开始变得难看。对于N = 4或N = 8,尽管这将是一个不错的选择。理想情况下,你需要大量的小数据集来同时排序,即如果你要排序8位值,那么你想要排序至少16个数据集 - 这样做跨 SIMD向量更难