是否有一种比快速排序更快的专用算法来重新排序数据ACEGBDFH?

时间:2012-05-10 07:10:27

标签: performance algorithm sorting optimization language-agnostic

我有一些来自硬件的数据。数据以32字节为单位,可能有数百万个块。数据块按以下方式分成两半(字母是一个块):

A C E G I K M O B D F H J L N P

或编号为

0 2 4 6 8 10 12 14 1 3 5 7 9 11 13 15

首先是所有具有偶数索引的块,然后是奇数块。是否有专门的算法来正确地重新排序数据(按字母顺序排列)?

约束主要是空间。我不想再分配另一个缓冲区来重新排序:再多一个块。但我还想保持低移动次数:一个简单的快速排序就是O(NlogN)。对于这种特殊的重新排序情况,O(N)中是否有更快的解决方案?

6 个答案:

答案 0 :(得分:7)

由于这些数据总是以相同的顺序排列,因此根本不需要经典意义上的排序。您不需要进行任何比较,因为您事先已经知道了两个给定数据点中的哪一个。

相反,您可以直接在数据上生成排列。如果将其转换为循环形式,则会准确地告诉您要进行哪些交换,将置换数据转换为有序数据。

以下是您的数据示例:

0 2 4 6 8 10 12 14 1 3  5  7  9 11 13 15
0 1 2 3 4 5  6  7  8 9 10 11 12 13 14 15

现在计算逆(我将跳过这一步,因为我在这里很懒,相反我上面给出的排列实际上已经是倒数)。

这是循环形式:

(0)(1 8 4 2)(3 9 12 6)(5 10)(7 11 13 14)(15)

因此,如果您想重新排序这样的结构序列,您可以

# first cycle
# nothing to do

# second cycle
swap 1 8
swap 8 4
swap 4 2

# third cycle
swap 3 9
swap 9 12
swap 12 6

# so on for the other cycles

如果您已经为逆而不是原始排列做了这个,那么您将获得具有经过验证的最小交换次数的正确序列。

修改

有关此类内容的详细信息,请参阅TAOCP中的“排列”一章。

答案 1 :(得分:3)

所以你有数据以

这样的模式进入

a 0 a 2 a 4 ... a 14 a 1 a 3 a 5 ... a 15

并且您希望将其排序为

b 0 b 1 b 2 ... b 15

通过一些重新排序,排列可以写成:

a 0 - > B'的子> 0

a 8 - > B'的子> 1
a 1 - > B'的子> 2
a 2 - > B'的子> 4
a 4 - > B'的子> 8

a 9 - > B'的子> 3
a 3 - > B'的子> 6
a 6 - > B'子> 12
a 12 - > B'的子> 9

a 10 - > B'的子> 5
a 5 - > B'的子> 10

a 11 - > B'的子> 7
a 7 - > B'的子> 14
a 14 - > B'的子> 13
a 13 - > B'的子> 11

a 15 - > B'的子> 15

因此,如果您想在临时t中仅使用一个块额外空间对其进行排序,则可以使用

在O(1)中完成此操作
t = a8;   a8 = a4;  a4 = a2;  a2 = a1;  a1 = t

t = a9;   a9 = a12; a12= a6;  a6 = a3;  a9 = t

t = a10; a10 = a5;  a5 = t

t = a11; a11 = a13; a13 = a14; a14 = a7; a7 = t

编辑:
一般情况(对于N!= 16),如果它在O(N)中是可解的,实际上是一个有趣的问题。我怀疑循环始终以满足p < N/2 && N mod p != 0的素数开始,并且索引具有像i n + 1 = 2i n mod N的重复,但我我无法证明这一点。如果是这种情况,导出O(N)算法是微不足道的。

答案 2 :(得分:1)

也许我是误会,但如果订单总是相同那么你可以“预编程”(即避免所有比较)最佳解决方案(这将是具有最小交换数量的交换从ABCDEFGHIJKLMNOP的字符串移动到哪一个,对于这么小的东西,你可以手工解决 - 见LiKao的回答)。

答案 3 :(得分:0)

我更容易用数字标记你的集合:

0 2 4 6 8 10 12 14 1 3 5 7 9 11 13 15

从14开始,将所有偶数移动到位(8个交换)。你会得到这个:

0 1 2 9 4 6 13 8 3 10 7 12 11 14 15

现在你需要另外3个掉期(9个带3个,7个带13个,11个带13个移动7个)。

共有11次掉期。不是一般解决方案,但它可以给你一些提示。

答案 4 :(得分:0)

您还可以将预期的排列视为地址位的混乱`abcd&lt; - &gt; dabc'(用abcd表示索引的各个位)如:

#include <stdio.h>

#define ROTATE(v,n,i) (((v)>>(i)) | (((v) & ((1u <<(i))-1)) << ((n)-(i))))

/******************************************************/
int main (int argc, char **argv)
{
unsigned i,a,b;

for (i=0; i < 16; i++) {
        a = ROTATE(i,4,1);
        b = ROTATE(a,4,3);

        fprintf(stdout,"i=%u a=%u b=%u\n", i, a, b);
        }

return 0;
}

/******************************************************/

答案 5 :(得分:-2)

那是count sort我相信