我遇到了这个问题:
给定{0,1,2,...,n-1}的排列P. (这里n = P。长度)
解释为什么以下算法按递增顺序对排列进行排序并给出最坏情况(伪代码)
PermutationSort(P)
for i = 0 to P.length - 1
while(P[i] != i)
t = P[i]
exchange P[i] with P[t]
(C ++代码)
void PermutationSort(int P[], int len)
{
for(int i = 0; i < len; i++)
while(P[i] != i)
{
int tmp;
tmp = P[i];
P[i] = P[tmp];
P[tmp] = tmp;
}
}
我完全不知道为什么要对排列P进行排序。
我整天都坐在这个问题上,但我仍然没有为什么对排列进行排序。
什么&#34;用P [P [i]]&#34;交换P [i];为什么我们最终得到P [i] = i然后终止内循环呢?
感谢任何提示或帮助。
答案 0 :(得分:1)
首先,请注意,如果从任意元素 k 开始,并重复应用排列 P 以获得类似链( k >→ P ( k )→ P ( P ( k ))→ P ( P ( P ( k )))→...),你会(因为总数)置换 P 中的元素数量是有限的,并且置换从不将两个输入映射到相同的输出)最终在 k 处结束。 cycle元素(k→ P ( k )→ P ( P ( k ))→...→ k )在 P 下被称为 k 的orbit,并且排列的每个元素都属于这样一个循环。
现在,让我们看一下你的算法的内循环对包含元素 i 的循环的作用。
如果 P ( i )= i ,即如果这个元素已经属于它,那么内部循环什么也不做外部循环移动到下一个元素。但是,如果 P ( i )≠ i ,则内循环设置 t = P ( i ),然后修改排列 P 以交换 P ( i )和 p 的(吨)。
交换后, P ( t )的新值是 P 的旧值( i ),即 t 。因此,元素 t 现在已正确排序,而 P ( i )现在包含旧值 P ( t )= P ( P ( i )),即循环中的(前)下一个元素。如果这是 i ,则循环中不再剩余元素,内循环结束;否则,包含 i 的循环已缩小一个元素,内循环重复。
因此,在内循环结束时,所有与 i (包括 i 本身)相同循环的元素都已移至它们的正确位置,因此从循环中移除,而其余的排列没有改变。
由于外部循环遍历排列中的每个元素,因此也保证至少访问每个循环一次。当然,我们正在修改内循环中的排列,但这没关系,因为内循环永远不会创建新的循环(多于一个元素);它只能打破现有的。
因此,第一次原始排列中的每个循环都被外循环访问,内循环对该循环进行排序和分解;在后续访问同一个原始循环时,该循环已经被排序,因此内循环什么都不做。
此观察还应允许您限制内循环执行的次数,从而确定算法的时间复杂度。