逆序对
逆序对是指在一个元素序列中,按照一定的大小比较方法,序列中任两个元素大小顺序颠倒的组合。
设 A[1..n] 是一个包含 n 个不同数的数组 . 如果在 i<j 的情况下 , 有 A[i]>A[j], 则 (i,j) 就称为 A 中的一个逆序对 .
对于一个给定待排序序列 , 其中的逆序对的发现与还原正是排序所要解决的事情 . 排序过程中一般是先发现逆序对再将其还原 , 由于这些让我们联想到了排序性能提高的一些方法 .
1. 一次还原操作 , 使得多组逆序对还原 .
eg: 共有 21 对 共有 10 对
7,6,5,4,3,2,1--(1 与 7 互换 )-->1,6,5,4,3,2,7
一次还原处理了 11 对
2. 一次对换操作后 , 尽量不要或者少产生额外的逆序对
eg: 共有 16 对 共有 11 对
7,6,5,1,3,2,4--(4 与 7 互换 )-->4,6,5,1,3,2,7
一次还原处理了 5 对 , 另外又多产生了 (4,1) 一对
在我观察的比较类排序中 , 快速排序体现了 1 却缺失了 2; 合并排序恰恰相反体现了 2 却缺失了 1.
关于逆序对的相关统计算法代码参见
/* Copyright (C) 2000-2007 Wang Pengcheng <wpc0000@163.com>
* Licensed to the Wang Pengcheng under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The LGPL licenses this file to You under the GNU Lesser General Public
* Licence, Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/lgpl.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mypackage.algorithm.unit02;
public class Inversion ...{
private static int tot;
/** *//**
*InsertionSort
*The time limit of this sort is O(n^2)
*<strong>O(n^2)</strong>
*@param element will be sorted
*/
private static <Type extends Comparable> void insertionSort(Type element[])...{
for(int j=1;j<element.length;j++)...{
Type key = element[j];
int i = j-1;
while( (i>=0)&&(element[i].compareTo(key)>0))...{
element[i+1] = element[i];
tot++;
i--;
}
element[i+1] = key;
}
}
/** *//**
*Merge used in the mergeSort
*<strong>O(n)</strong>
*@param element Type[] the elements to be merged
*@param p int the begin of the first elements
*@param q int the end of the first elements
*@param r int the end of the second elements
*/
private static <Type extends Comparable> void merge(Type element[],int p,int q,int r)...{
int nl = q-p+1;
int nr = r-q;
Type[] lElement,rElement;
lElement = (Type[])java.lang.reflect.Array.newInstance(element.getClass().getComponentType(),nl);
rElement = (Type[])java.lang.reflect.Array.newInstance(element.getClass().getComponentType(),nr);
for(int i=0;i<nl;i++)...{
lElement[i] = element[p+i];
}
for(int i=0;i<nr;i++)...{
rElement[i] = element[q+i+1];
}
int i=0,j=0;
int k = p;
while((i<nl)&&(j<nr))...{
if(lElement[i].compareTo(rElement[j])<=0)...{
element[k] = lElement[i];
i++;
}else...{
element[k] = rElement[j];
j++;
tot+=nl-i;
}
k++;
}
while(i<nl)...{
element[k] = lElement[i];
i++;
k++;
}
while(j<nr)...{
element[k] = rElement[j];
j++;
k++;
}
}
/** *//**
*mergeSort
*Sort the elements by the compareTo method
*<strong>O(nlgn)</strong>
*@param element Type[] that will be sorted
*@param p the begin of the list will be sorted
*@param r the end of the list will be sorted
*/
private static <Type extends Comparable> void mergeSort(Type element[],int p,int r)...{
if(p<r)...{
int q = (p+r)/2;
mergeSort(element,p,q);
mergeSort(element,q+1,r);
merge(element,p,q,r);
}
}
private static <Type extends Comparable> void mergeSort(Type element[])...{
mergeSort(element,0,element.length-1);
}
/** *//**
* Count the inversion number by O(nlgn)
* @param <Type> inversion number type
* @param element inversion number list
* @return count number of inversion
*/
public static <Type extends Comparable> int countMerge(Type element[])...{
tot=0;
mergeSort(element.clone());
return tot;
}
/** *//**
* Count the inversion number by O(n^2)
* @param <Type> inversion number type
* @param element inversion number list
* @return count number of inversion
*/
public static <Type extends Comparable> int countInsertion(Type element[])...{
tot=0;
insertionSort(element.clone());
return tot;
}
/** *//**
* @param args
*/
public static void main(String[] args) ...{
Integer[] a = ...{4,6,5,1,3,2,7};
System.out.println(Inversion.countMerge(a));
}
}
最后让我们牢记 :
摘《李开复:算法的力量 》算法并不局限于计算机和网络
举一个计算机领域外的例子:在高能物理研究方面,很多实验每秒钟都能几个 TB 的 数据量。但因为处理能力和存储能力的不足,科学家不得不把绝大部分未经处理 的数据丢弃掉。可大家要知道,新元素的信息很有可能就藏在我们来不及处理的数据里面。同样的,在其他任何领域里,算法可以改变人类的生活。例如人类基因的 研究,就可能因为算法而发明新的医疗方式。在国家安全领域,有效的算法可能避免下一个 911 的发生。在气象方面,算法可以更好地预测未来天灾的发生,以拯 救生命。
所以,如果你把计算机的发展放到应用和数据飞速增长的大环境下,你一定会发现;算法的重要性不是在日益减小,而是在日益加强。
谢谢大家。
参考书籍
《 Inroduction to Algorithms 》 Thomas H.Cormen,Charles E.Leiserson,Ronald L. Rivest,Clifford Stein. 机械工业出版社
《数据结构》殷人昆,陶永雷,谢若阳,盛绚华 清华大学出版社
《算法艺术与信息学竞赛》刘汝佳,黄亮 清华大学出版社
《李开复:算法的力量》 http://www.ieee.org.cn/dispbbs.asp?boardID=60&ID=31651