3.2在isertSort.java程序(清单3.3)中给ArrayIns类加一个median()方法.这个方法将返回 数组的中间值.(回忆一下,数组中一半数据项比中间值大,一半数据项比中间值小。)
3.3在insertSort.java程序(清单3.3)中增加一个名为noDups()的方法,这个方法从已经有 序的数组中删掉重复的数据项而不破坏有序性。(可以用insertionSort()方法对数据排序, 或者也可以简单地用main()方法将数据有序地插入到表中。)一种解决方法是每发现一个重 复的数据,就从这个位置开始到数组结尾都向前移动一个位置,但这样就导致消耗很长的 O(N2)的时间级,起码在有很多重复数据项的情况下是这样的。在设计的算法中,不论有多 少重复数据,要确保数据项最多只能移动一次。这样算法只消耗O(N)数量级的时间。
3.5修改insertSort.java程序(清单3.3)中的insertionSort()方法,使它可以计算排序过 程中复制和比较的次数并显示出总数。为计算比较的次数,要把内层while循环的两个条件分开。用这个程序测量各种数量的逆序数据排序的复制和比较次数。结果满足O(N2)吗?与已经基本有序的数据(仅有很少的数据无序)的情况一样吗?从对基本有序数据排序的表现中可得出关于这个算法效率的什么结论?
3.6有一个有趣的方法用来删除数组中相同的数据项。插入排序算法中用一个循环嵌套算法,将数组中的每一个数据项与其他数据项一一比较。如果要删除相同的数据项,可以这样做(参见第30.2章第2.6小节)。修改insertSort.java中的insertionSort()方法,使它可以在排序过程中删除相同的数据项。方法如下:当找到一个重复数据项的时候,通常用一个小于任何值的关键值来改写这个相同数据项(如果所有值都是正数,则可取-1)。于是,一般的插入排序算法就会像处理其他数据项一样,来处理这个修改了关键值的数据项,把它移到下标为0的位置。从现在开始,算法可以忽略这个数据项。下一个相同的数据项将被移到下标为1的位置,依此类推。排序完成后,所有相同的数据项(现在关键值为-1)都在数组的开头部分。可以改变数组的容量并把需要的数据前移动数组下标为0的位置。
public class ArrayIns {
private long[] a ;
private int nElems;
public ArrayIns(int max){
a = new long[max];
nElems = 0;
}
public void insert(long value){
a[nElems] = value;
nElems++;
}
public void display(){
for(int j = 0;j < nElems;j++)
System.out.print(a[j]+" ");
System.out.println("");
}
//===========================================================================
//插入排序
public void insertSort(){
int in,out;
for(out =1;out<nElems;out++){
long temp = a[out];//remove marked item
in = out;//start shifts at out
while(in>0&&a[in-1]>=temp){
a[in]=a[in-1];//shift item to right
--in;//go left one position
}
a[in]=temp;//insert marked item
}
}
//==========================================================================
//编程作业 3.5
public int insertSort1(){
int in,out;
int compare = 0;//比较次数
int copy = 0;//复制次数
for(out=1;out<nElems;out++){
long temp =a[out];
in = out;
while(in>0){
if(a[in-1]>temp){
a[in]=a[in-1];
--in;
compare++;
copy++;
}
else{
compare++;
break;
}
}
a[in]=temp;
}
return compare+copy;
}
//======================================================================
//编程作业3.6
public void insertSort2(){
int in,out,count=0;
for(out=1;out<nElems;out++){
long temp = a[out];
in = out;
while(in>0&&a[in-1]>=temp&&a[in-1]!=-1){
if(a[in-1]==temp){
temp=-1;
count++;
}
a[in]=a[in-1];
--in;
}
a[in]=temp;
}
nElems-=count;
for(int i=0;i<nElems;i++){
a[i]=a[i+count];//把排序好的元素向前移动count个位置
}
}
//===================================================================
//编程作业3.2
public long median(){
this.insertSort();//先排序再取中间值
return a[nElems/2];
}
//=============================================================
//编程作业3.3
public void noDups(){
this.insertSort();//先排序
int holenumber = 0;
final int FLAG = -1;
for(int i=0;i<nElems;i++){
for(int j=i+1;j<nElems;j++){
if(a[i]==a[j]&&a[j]!=FLAG){
a[j]=FLAG;
holenumber++;
}
}
}
int firsthole=-1;
for (int i = 0; i < nElems; i++) {
if (a[i] == FLAG && firsthole == -1) {
firsthole = i;
}
else if (a[i] != FLAG && firsthole != -1) {
a[firsthole++] = a[i];
}
}
nElems -= holenumber;
}
}
public class InsertSortApp {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int maxSize=100;
ArrayIns arr;
arr = new ArrayIns(maxSize);
arr.insert(77);
arr.insert(99);
arr.insert(44);
arr.insert(55);
arr.insert(22);
arr.insert(88);
arr.insert(11);
arr.insert(00);
arr.insert(66);
arr.insert(33);
arr.display();
arr.insertSort();
arr.display();
arr = new ArrayIns(maxSize);
arr.insert(2);
arr.insert(3);
arr.insert(4);
arr.insert(3);
arr.insert(3);
arr.insert(1);
arr.insert(2);
arr.insert(1);
arr.insert(1);
arr.insert(1);
System.out.println("插入重复值后:");
arr.display();
arr.noDups();
System.out.println("删除重复值后:");
arr.display();
arr = new ArrayIns(maxSize);
int count;
for (int i = 19; i >= 0; i--) {// 初始化为逆序数组
arr.insert(i);
}
arr.insert(19);
arr.insert(9);
arr.insert(0);
arr.display();
count = arr.insertSort1();
arr.display();
System.out.println("逆序数组比较复制总数:" + count); // 满足O(N^2) 229. 230.
arr = new ArrayIns(maxSize); // create the array
for (int i = 19; i >= 0; i--) {// 初始化为逆序数组
arr.insert(i);
}
arr.insert(19);
arr.insert(9);
arr.insert(0);
arr.display();
count = arr.insertSort1();
arr.display();
System.out.println("顺序数组比较复制总数:" + count);
arr = new ArrayIns(maxSize); // create the array
arr.insert(2);
arr.insert(3);
arr.insert(4);
arr.insert(3);
arr.insert(3);
arr.insert(1);
arr.insert(2);
arr.insert(1);
arr.insert(1);
arr.insert(1);
System.out.println("插入重复值后:");
arr.display();
arr.insertSort2();
System.out.println("删除重复值后:");
arr.display();
}
}