我正在寻找非递归奇偶合并排序算法,并找到了两个来源:
- Sedgewick R.的一本书
- 这个SO问题
这两种算法都是相同但错误的。生成的排序网络不是一个奇偶合并排序网络。
这是一个具有32个输入的生成网络的图像。在两条水平线之间的垂直线表示比较值a[x]和a[y],如果大于则交换数组中的值。
(来源:flylib.com)
(可点击)
我从Java代码复制了C代码,并用printf函数替换了exch函数以打印交换的候选项。
当人们绘制对数图时,可以看出生成了太多的对。
有人知道如何修复这个算法吗?
我为什么需要非递归版本?
我想将这个排序网络转换成硬件。在非递归算法中插入管道阶段很容易。
我还调查了递归版本,但是将算法转换为流水线硬件太复杂了。
我的C代码:
#include <stdlib.h>
#include <stdio.h>
void sort(int l, int r)
{ int n = r-l+1;
for (int p=1; p<n; p+=p)
for (int k=p; k>0; k/=2)
for (int j=k%p; j+k<n; j+=(k+k))
for (int i=0; i<n-j-k; i++)
if ((j+i)/(p+p) == (j+i+k)/(p+p))
printf("%2i cmp %2i\n", l+j+i, l+j+i+k);
}
int main(char* argv, int args)
{ const int COUNT = 8;
sort(0, COUNT);
}
结果:
0 -o--------o-------------------------o---------------o-------------------------
| | | |
1 -o--------|-o------o----------------|-o-------------o-o-----------------------
| | | | | |
2 -o-o------o-|------o-o--------------|-|-o----o--------o-o---------------------
| | | | | | | | |
3 -o-o--------o--------o--------------|-|-|-o--|-o--------o-o-------o-----------
| | | | | | | |
4 -o-o-o----o---o----o-----o----------o-|-|-|--o-|-o--------o-o-----o-o---------
| | | | | | | | | | | | | |
5 -o-o-o----|-o-|-o--o-o---o-o---o------o-|-|----o-|-o--------o-o-----o-o---o---
| | | | | | | | | | | | | |
6 -o-o-o-o--o-|-o-|----o-o---o-o-o-o------o-|------o-|----------o-o-----o-o-o-o-
| | | | | | | | | | | | | |
7 -o-o-o-o----o---o------o-----o---o--------o--------o------------o-------o---o-
当我知道正确的交换对并且算法等于图像时,我会将其翻译成VHDL代码,在硬件平台上进行测试。
其他开源硬件排序网络实现:
附录:
奇偶归并排序(也称为Batcher's sort)类似于比特位排序(不要与Batcher的比特位排序混淆)。但在硬件中,这种算法具有比比特位排序更好的规模复杂度,而延迟相同。
与快速排序等快速软件算法相比,这些算法可以使用较少的资源。
维基百科:奇偶归并排序
注意:
由于排序网络是静态的且独立于输入值,因此不需要比较和交换即可生成网络。这是它可以转换为硬件的原因之一。我的代码生成用于比较操作的索引。在硬件中,这些垂直连接将被比较和交换电路替换。因此,未排序的数据将通过网络传输,在输出端它将被排序。