逆序对inversion
在正序排序算法里,对输入序列中的任一对元素i、j,如果排序靠前的元素i小于靠后的元素j,那么元素i、j组成一个正序对,否则组成一个逆序对(inversion)。
自然,当我们把输入序列中这些inversions都消除了,排序就完成了。
交换相邻的元素是消除inversion的方法之一。接下来我们要分析的就是这种排序算法。
inversion个数与所需交换次数是怎样的关系呢?
以序列 4,5,3,1,0,2 为例,当我们交换相邻的逆序元素(3,1)之后,序列变成4,5,1,3,0,2,我们消除了几个inversion?答案是只有1个。为什么,先来看原本排在前面的元素3,交换虽然使它的次序向后移动了一位,但是除了1之外,原来在它前面的4,5依然在它前面,原来在后面0,2也依然排在它后面,也就是说,除了inversion(3,1)的次序被纠正了,3和其他元素的相对次序没有发生改变,而交换前排在后面的1的情况也是一样。所以可以得出结论:交换相邻元素形成的逆序对只能消除一个inversion。
所以,一个序列初始时刻有几个inversions,排序过程中对相邻元素的交换操作就需要进行几次。
总时长与inversion个数的关系
对于一个长度为N的输入序列,假设inversion数量为I,因为除了交换之外还需要O(N)的额外工作,所以总时长为O(N+I)。
平均情况下,I是多少?
最优情况下,输入序列呈正序排列,I = 0;
最坏情况下,输出序列呈倒序排列,I = N(N-1)/2;
所以平均情况下,I = N(N-1)/4。
综上所述,通过交换相邻元素进行排序的算法所需平均时间为Ω(N^2 )。像插入排序、选择排序、冒泡排序都属于这一类算法。这个定理告诉我们要想提高排序算法的效率,不能只对相邻的元素做交换,还需要对相距较远的元素做交换,使得一次交换消除不止一个inversion。