【问题标题】:Is there a specialized algorithm, faster than quicksort, to reorder data ACEGBDFH?是否有一种比快速排序更快的专门算法来重新排序数据 ACEGBDFH?
【发布时间】:2014-05-16 04:57:51
【问题描述】:

我有一些来自硬件的数据。数据以 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) 中是否有更快的解决方案?

【问题讨论】:

  • 在 O(n) 复杂度中无法进行排序。
  • @shiplu.mokadd.im:一般情况下是这样,但是这个数据已经部分排序了
  • 当你说“总是按照下面的方式”时,你的意思是顺序总是给定的——第一个块是第一块,第二块是第九块,第三块是第二块,等等?如果是这样,那么您肯定可以编写代码来明确地重新排列它们吗?
  • 您确实需要解释您的数据是如何部分排序的。它只是分成两个排序的一半吗?还是两半总是分别包含奇数/偶数元素?
  • 好的,我似乎有“数百万块”部分,这表明这里有一些比我在回答中假设的要多。澄清一下:如果有 18 个区块而不是 16 个,那么额外的两个区块会去哪里?在您的情况下是否可能有 18 个块,或者这会被禁止。在重新阅读后,我现在如何理解这一点,是您收到的模式是:Odd numbered blockeven numbered blocks,而不是 16 个块的固定模式A C E G I K M O B D F H J L N P,可能会像我最初假设的那样重复。这是正确的吗?

标签: performance algorithm sorting optimization language-agnostic


【解决方案1】:

由于这些数据总是按相同的顺序排列,因此根本不需要传统意义上的排序。您不需要任何比较,因为您已经提前知道两个给定数据点中的哪一个。

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

以下是您的数据示例:

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 中的排列章节。

【讨论】:

  • 但有什么意义,因为计算置换的循环形式是 O(N^2)?还是我不熟悉 O(N) 算法? -1,直到你详细说明。 :D 对于他的数据具有的特定形式,你能以某种方式在 O(N) 中为任意 N 生成它吗?
  • 那么现在,如何在不使用大量内存的情况下计算任意数量块 N(N 是偶数)的排列?
  • @svinja 正如 OP 所写,数据以他描述的方式进入always。既不需要也不需要预先计算任意 N。
  • @svinja 好吧,算了 :-) 愚蠢的我。我怎么能理解问题中的always,就像它的意思是always...
  • 它以这种形式出现(先排序赔率,然后排序偶数),但它可以是数百万个块长,而不仅仅是 16 个。至少我是这样理解的,否则“数百万个块”没有意义。
【解决方案2】:

所以你有像这样的模式进入的数据

a0 a2 a4...a14 a1 a3 a5...a15

你想让它排序到

b0 b1 b2...b15

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

a0 -> b0

a8 -> b1
a1 -> b2
a2 -> b4
a4 -> b8

a9 -> b3
a3 -> b6
a6 -> b12
a12 -> b9

a10 -> b5
a5 -> b10

a11 -> b7
a7 -> b14
a14 -> b13
a13 -> b11

a15 -> b15

因此,如果您想在临时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 的素数开头,并且索引的重复频率类似于 in+1 = 2in mod N,但我不是能够证明。如果是这种情况,推导 O(N) 算法就很简单了。

【讨论】:

  • 谢谢,这是写立考答案的另一种方式。现在,我怎样才能对任意数量的块 N(N 是偶数)执行此操作?
  • @drhirsh:好的,你的方法直接推导掉期而不先计算逆。而且你不需要像我那样大量的临时人员,通过相反的方向交换。我想下次我必须花更多的时间来完善我的第一个想法。为这个漂亮的改进 +1。
【解决方案3】:

也许我理解错了,但如果订单总是相同与给定的订单,那么你可以“预先编程”(即避免所有比较)最佳解决方案(这将是从给定到 ABCDEFGHIJKLMNOP 的字符串中具有最小交换次数的那个,对于这么小的东西,您可以手动计算 - 请参阅 LiKao 的答案)。

【讨论】:

  • 我看不到编辑距离是怎么来的。编辑距离通常处理从一个序列到另一个序列的删除/插入/替换类型的更改,而不是排列。如果你需要排列,这就是你应该使用的。
  • 哦,对不起,我虽然它包括交换字符。会更新。
  • 至少标准编辑距离不包括交换。也许有一个专门的版本。如果你能找到一个,我会对算法的改变很感兴趣,让它考虑交换。
【解决方案4】:

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

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 次交换。不是一个通用的解决方案,但它可以给你一些提示。

【讨论】:

    【解决方案5】:

    您还可以将预期的排列视为地址位 `abcd 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;
    }
    
    /******************************************************/
    

    【讨论】:

      【解决方案6】:

      我相信那是count sort

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多