如果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获取它,如果它来自较小的索引,则从其中获取。datainfo
当然,这种简单的方法要求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.