在获得有关最终排序数组的额外信息时,有效地对整数数组进行排序

时间:2013-04-29 21:02:19

标签: sorting

假设我们有一个名为data

的整数数组
 3
 2
 4
 5
 2

此外,我们还有以下相同大小的数组info

 1
 4
 0
 2
 3

info的每个值表示第一个数组的索引。例如,第一个值是1,这意味着在位置0中,最终排序的数组将具有值data[info[0]]

通过遵循此逻辑,最终排序的数组将如下:

data[info[0]] => 2
data[info[1]] => 2
data[info[2]] => 3
data[info[3]] => 4
data[info[4]] => 5

我想对data数组进行就地排序,而不使用任何大小为N的额外内存,其中N的大小为data数组。另外,我希望总操作量尽可能小。

我一直试图想出解决问题的方法,但是我想不出任何不会使用额外内存的东西。请记住,这些是我自己对我正在实施的系统的限制,如果不能保留这些限制,那么我可能不得不考虑别的。

任何想法都会受到赞赏。

提前谢谢

2 个答案:

答案 0 :(得分:2)

为什么不简单

for i in 0..n-1 : 
   info[i] := data[info[i]]

info现在保存已排序的数组。如果它必须在data中,请将其复制回来,下一步:

for i in 0..n-1 : 
    data[i] := info[i]
总的来说,

2*n份。

答案 1 :(得分:1)

如果info数组不需要保持不变,您可以将其用作O(n)中的附加存储和排序:

for(int i = 0; i < n; ++i) {
    int where = info[i];
    if (where == i) continue;
    info[i] = data[i];
    data[i] = i < where ? data[where] : info[where];
}

如果data的元素已经在正确的位置,我们会跳过该索引。否则,请记住info数组中的元素,并将正确的元素写入data,如果它来自较大的索引则从data获取,并从info获取它来自较小的指数。

当然,这种简单的方法要求infodata数组的类型相同,并且通常3*n个副本。

如果data元素无法存储在info数组中,我们可以按照info中的周期进行操作:

for(int i = 0; i < n; ++i) {
    // Check if this is already in the right place, if so mark as done
    if (info[i] == i) info[i] = -1;

    // Nothing to do if we already treated this index
    if (info[i] < 0) continue;

    // New cycle we haven't treated yet
    Stuff temp = data[i];    // remember value
    int j = info[i], k = i;
    while(j != i) {
        // copy the right value into data[k]
        data[k] = data[j];
        // mark index k as done
        info[k] = -1;
        // get next indices
        k = j;
        j = info[j];
    }
    // Now close the cycle
    data[k] = temp;
    info[k] = -1;
}

n - F + Cdata元素的副本,其中F是已经在正确位置的元素数量(排序排列的固定点)和{{1} }是排序排列中长度C的循环数。这意味着副本数量最多为> 1