如果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
当然,这种简单的方法要求info
和data
数组的类型相同,并且通常会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 + C
复制data
元素,其中F
是已经在正确位置的元素的数量(排序排列的固定点),并且C
是排序排列中长度的循环数> 1
。这意味着副本的数量最多为3*n/2
.