Higharray.java 源码
/*
* 下述的作业题源自<<Java数据结构和算法(第二版)>>每章结束后留给的问题,
* 它们涵盖了每章的所有重点。目地在于自测,以确保自己已经基本理解该章的内容。
* 题源:第2章 数组
* 作者:半点闲
* 时间:2008.6.19
*/
package Higharray;
/**
*
* @author bdx
*/
class HighArray{
public HighArray(int max) //constructor
{
a = new long[max]; //create the array
nElems = 0; //no items yet
}
public boolean find (long searchkey) //find specified value
{
int j;
for(j=0; j<nElems; j++) //for each element,
if(a[j] == searchkey) //found item?
break; //exit loop before end
if(j == nElems) //gone to end?
return false; //yes,can't find it
else
return true; //no,found it
}
public void insert (long value) //put element into array
{
a[nElems] = value; //insert it
nElems++; //increment size
}
public boolean delete (long value)
{
int j;
for(j=0; j<nElems; j++) //look for it
if(value == a[j])
break;
if(j == nElems) //can't find it
return false;
else
{
for(int k=j; k<nElems; k++) //move higher ones down
a[k] = a[k+1];
nElems--;
return true;
}
}
public void display() //displays array contents
{
for(int j=0; j<nElems; j++) //for each element
System.out.print(a[j] + " "); //display it
System.out.println();
}
/**
* 编程作业:2.1向highArray.java程序(清单2.3)的HighArray类添加名为getMax()的方法,
* 它返回数组中最大关键字的值,当数组为空时返回-1。向main()中添加一些代码来使用这个方法。
* 可以假设所有关键字都是正数。
* 功能:获取数组中最大关键字的值。当数组为空时返回-1。
* @return long
*/
public long getMax(){
if(nElems == 0) return -1; //数组为空。
long lmax = a[0];
for(int i=1; i<nElems; i++)
if(lmax < a[i]) lmax = a[i];
return lmax;
}
/**
* 编程作业:2.2修改编程作业2.1中的方法,使之不仅返回最大的关键字,而且还将关键字从数组中删除。
* 将这个方法命名为removeMax()。
* 功能:将最大关键字从数组中删除。成功返回true,否则false。
* @return boolean
*/
public boolean removeMax (){
/**
* 思考:找到最大关键字可以通过现有getMax()方法来实现,删除功能可以通过现有的delete(long)
* 来实现。
*/
if(getMax() == -1) return false;
return delete(getMax());
}
/**
* 编程作业:2.6 向highArray.java程序(清单2.3)的HighArray类中加入一个noDup()的方
* 法,使之可以将数组中的所有重复数据项删除.即如果数组中有三个数据项的关键字为17,
* noDup()方法将会删除其中的两个.不必考试保持数据项的顺序.一种方法是先用每一个数据
* 项比较,并用null(或是一个不会用在真正的关键字中的特殊值)将重复的数据项覆盖掉。然
* 后将所有的null删除,当然还要缩小数组的大小。
*/
public void noDup()
{
//标记部分
int nCount = 0; //标记计数器。
for(int i=0; i<nElems; i++)
for(int j=0; j<i; j++)
if(a[j] == a[i])
{
if(a[i] != -1) //排除特殊标记
{
a[i] = -1; //特殊标记,假设用户不会输入负值。
nCount++;
}
}
//调整部分
long[] b = new long[nElems - nCount];
int nLength = 0;
for(int i=0; i<nElems; i++)
if(a[i] != -1)
{
b[nElems - nCount - 1 - i] = a[i];
nLength++;
}
//赋值部份
nElems = nLength;
a = b;
}
private long[] a; //ref to array a
private int nElems; //number of data items
}
public class HighArrayApp{
public static void main (String[] args){
int maxSize = 100; //array size
HighArray arr; //reference to array
arr = new HighArray(maxSize); //create the array
arr.insert(77); //insert 10 items
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(); //display array
int searchKey = 35;
if(arr.find(searchKey))
System.out.println("Found " + searchKey);
else
System.out.println("Can't find " + searchKey);
arr.delete(00); //delete 3 items
arr.delete(55);
arr.delete(99);
arr.display(); //display array
System.out.println("默认演示结束");
//编程作业:2.1
if(arr.getMax() != -1)
{
System.out.println("当前数组中最大的数是:" + arr.getMax());
System.out.println("删除最大关键字:" + arr.removeMax());
}
arr.display(); //display array
System.out.println("编程作业:2.1演示结束");
/**
* 编程作业:2.3编程作业2.2中的removeMax()方法提供了一种通过关键字值进行数组排序的方
* 法。实现一个排序方案,要求不修改HighArray类,只需对main()中的代码进行修改。这个方
* 法需要第二个数组,在排序结束时数组数据项是逆序排列的。(这个方法是第3章“简单排序”中选
* 择排序的一个变体.)
* 作者声明:下面代码只完成上述要求,算法不做其它处理。
*/
HighArray higthSort = new HighArray(maxSize);
for(int i=0; i<maxSize; i++){
higthSort.insert(arr.getMax());
arr.removeMax();
}
higthSort.display(); //display array
System.out.println("编程作业:2.3演示结束");
/**
* 编程作业:2.6
*/
arr.insert(55);
arr.insert(44);
arr.insert(44);
arr.insert(55);
arr.noDup();
arr.display();
System.out.println("编程作业:2.6演示结束");
}
}
OrderedApp.java 部分
/* * 下述的作业题源自<<Java数据结构和算法(第二版)>>每章结束后留给的问题, * 它们涵盖了每章的所有重点。目地在于自测,以确保自己已经基本理解该章的内容。 * 题源:第2章 数组 * 作者:半点闲 * 时间:2008.6.19 */ /** * 编程作业:2.4修改orderedArray.java程序(清单2.4)使insert()、delete()与find()方法一 * 样都使用二分查找,正如书中所建议的那样。 * 编程作业:2.5向OrderdApp.java程序(清单2.4)的OrdArray类加入一个merge()方法,使之 * 可以将两个有序的源数组合并成一个有序的目的数组。在main()中添加代码,向两个源数组中 * 插入随机数,调用merge()方法,并将结果目的数组显示出来。两个源数组的数据项个数可能不 * 同。在算法中需要先比较数组中的关键字,从中选出最小的一个数据项复制到目的数组。同时还 * 要考虑如何解决当一个源数组的数据项已经取完而另一个还剩一些数据项的情况。 */ package OrderedApp; import java.util.Random; /** * * @author bdx */ public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { int maxSize = 100; //array size OrdArray arr = new OrdArray(maxSize); //create the array 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); int searchKey = 55; //serch for item if( arr.find(searchKey) != arr.size() ) System.out.println("Found" + searchKey); else System.out.println("Can't find" + searchKey); arr.display(); //display items arr.delete(00); //delete 3 items arr.delete(55); arr.delete(99); arr.display(); //display items again System.out.println("默认演示结束。"); /** * 编程作业:2.5 */ OrdArray arr1 = new OrdArray(10); OrdArray arr2 = new OrdArray(5); Random random1 = new Random (); Random random2 = new Random (); for(int i=0; i<10; i++){ arr1.insert(Math.abs(random1.nextInt()%1000)); } for(int i=0; i<5; i++){ arr2.insert(Math.abs(random2.nextInt()%1000)); } arr1.display(); arr2.display(); OrdArray arr3 = OrdArray.merge(arr1, arr2); arr3.display(); System.out.println("编程作业:2.5演示结束。"); } } class OrdArray{ public OrdArray (int max) //constructor { a = new long[max]; nElems = 0; } public int size (){ return nElems; } public int find (long searchKey){ int lowerBound = 0; int upperBound = nElems - 1; int curIn; while(true){ curIn = (lowerBound + upperBound) / 2; if(a[curIn] == searchKey) return curIn; //found it else if(lowerBound > upperBound) return nElems; //can't find it else { if(a[curIn] < searchKey) lowerBound = curIn + 1; //it's in upper half else upperBound = curIn - 1; //it's in lower half } } } public void insert (long value) { /** * 作业2.4 * 算法说明:用"二分查找"找插入值合适位置。插入后的数组中的数据项按升序排列。 * 注明:为了减少检查用户输入的值与数组中的数据项是否有重复的代码,现假设用 * 户输入的值都是不重复的。 */ int lowerBound = 0; int upperBound = nElems - 1; int curIn = lowerBound; while (true) { curIn = (lowerBound + upperBound) / 2; //拆分 /** * lowerBound = upperBound,范围是一个数据项所以还需要再一次循环。 * lowerBound > upperBound,则范围已经不存在了。 */ if(lowerBound > upperBound) break; if(a[curIn] < value) lowerBound = curIn + 1; else upperBound = curIn - 1; } for(int k=nElems; k>curIn; k--) a[k] = a[k - 1]; a[lowerBound] = value; nElems++; } public static OrdArray merge (OrdArray arr1, OrdArray arr2) { /** * 编程作业:2.5 * merge()方法,使之可以将两个有序的源数组合并成一个有序的目的数组......两 * 个源数组的数据项个数可能不同。在算法中需要先比较数组中的关键字,从中选出 * 最小的一个数据项复制到目的数组。同时还要考虑如何解决当一个源数组的数据项 * 已经取完而另一个还剩一些数据项的情况。 * * 算法说明:力求完成上述作业求,同时让算法清晰,其它情况都不予处理(如: * 检查参数中的数组是否为空等等)。 */ int nLen1 = arr1.size(); int nLen2 = arr2.size(); int i = 0, j = 0; OrdArray ret = new OrdArray (nLen1 + nLen2); while(i < nLen1 && j < nLen2) { if(arr1.getValue(i) < arr2.getValue(j)) { ret.insert(arr1.getValue(i++)); } else { ret.insert(arr2.getValue(j++)); } } if(i == nLen1) // 如果array1已经被拷贝完毕就拷贝array2的元素 { while (j < nLen2) ret.insert(arr2.getValue(j++)); } else // 如果array2已经被拷贝完毕就拷贝array1的元素 { while (i < nLen1) ret.insert(arr1.getValue(i++)); } return ret; } public long getValue (int index){ /** * 功能:返回给定索引值的数据项。 */ return a[index]; } public boolean delete (long value) { int j = find (value); if(j == nElems) //can't find it return false; else { for(int k=j; k<nElems; k++) //move bigger ones down a[k] = a[k+1]; nElems--; //decrement size return true; } } public void display() //displays array contents { for(int j=0; j<nElems; j++) //for each element System.out.print(a[j] + " "); // display it System.out.println(); } private long[] a; //ref to array a private int nElems; //number of data items }