min=in;//则得到一个更小的数
swap(out,min);//且交换之
}//endfor(outer)
}//endselectionSort()
privatevoidswap(intone,inttwo)
{
doubletemp=a[one];
a[one]=a[two];//实现交换
a[two]=temp;
}
}//endclassArraySel
classSelectSortDemo{
publicstaticvoidmain(String[]args)
{
intmaxSize=100;//数组初始大小为100
ArraySelarr;
arr=newArraySel(maxSize);;//建立排序数组
arr.insert(50);//插入8个数
arr.insert(32);
arr.insert(63);
arr.insert(97);
arr.insert(75);
arr.insert(13);
arr.insert(26);
arr.insert(45);
System.out.println("排序前:
");
arr.display();
arr.selectionSort();//进行冒泡排序
System.out.println("排序后:
");
arr.display();
}//endmain()
}//endclassSelectSortDemo
在main()方法中通过调用方法insert(doublevalue)插入了8个数,然后调用方法selectionSort()进行排序,display()方法用来输出数据,其结果输出如图6-3所示。
图6-3【例6.3】的运行结果
上面介绍的几种排序算法各有特点,其中插入排序最简单,当序列中的数“基本有序”或n值较小时,它是最佳的排序方法,因此长将它和其它的排序方法结合在一起使用。
冒泡排序适合于排序数据数目不是很多的情况,但是它的操作代价较高,如果有N个数据参加排序,则使用冒泡算法的运算次数是N3数量级的量;选择排序和插入排序两个算法的代价比冒泡算法低一个数量级,运算次数在N2数量级。
除了上述讲的三种方法外,还有其它许多种排序方法,例如快速排序、归并排序、堆排序等。
6.1.2查找
查找(Searching)是根据给定的某个值,在一个数据集合或数据序列中确定一个其关键字等于给定值的数据元素。
若数据集合或数据序列中存在这样的一个数据元素,则称查找是成功的,此时查找的结果为给出整个数据元素的信息,或指示该数据元素在数据集合或数据序列中的位置;若数据集合或数据序列中不存在关键字等于给定值的数据元素,则称查找不成功。
例如,表6-1为某学生自然班情况,学生的学号为关键字。
假设给定值为20020115,则通过查找可得该学生的姓名、性别等,此时查找是成功的。
若给定值为20020136,则由于表中没有关键字为20020136的记录,则查找不成功。
表6-1学生自然班情况
学号
姓名
性别
籍贯
其它
┇
┇
┇
┇
20020115
李明
男
北京
20020116
刘丽
女
江西
┇
┇
┇
┇
由于查找需要处理大量的数据,所以查找过程可能会占用较多的系统时间和系统内存;为了提高查找操作的效率,需要精心设计查找算法来降低执行查找操作的时间和空间代价。
较常用的查找算法有顺序查找、折半查找等。
1、顺序查找
顺序查找(SequentialSearch)是最简单的查找算法,它的查找过程为:
从数据序列的第一个数据开始,若某个关键字和给定值比较相等,则查找成功;反之,若直至最后一个数据,其关键字和给定值比较都不等,则表明数据序列中没有所查关键字,查找不成功。
顺序查找对于数据序列没有特殊的要求,这个序列可以是排好序的,也可以是未排好序的,对于查找操作都没有影响。
在数据序列中数据数目不多时,使用顺序查找非常方便。
当然,顺序查找也可以从数据序列的最后一个数据开始。
【例6.4】顺序查找
/*ProgramnameSqSearch.java
一个顺序查找的例子
*/
publicclassSqSearch{
//数据数组
publicstaticint[]data={50,32,63,97,75,13,26,45};
publicstaticvoidmain(String[]args)
{if(sequence(63))//查找63
System.out.println("Thedata63found.");
else
System.out.println("Thedata63nofound!
");
if(sequence(25))//查找25
System.out.println("Thedata25found.");
else
System.out.println("Thedata25nofound!
");
}
publicstaticbooleansequence(intkey){
inti;//数组下标变量
for(i=0;i<8;i++)
{
System.out.print("["+data[i]+"]");//输出数据
if(key==data[i]){//若查找到数据
System.out.println("");
returntrue;//则返回true
}
}
System.out.println("");
returnfalse;//否则返回false
}
}
输出结果如图6-4所示。
图6-4【例6.4】的运行结果
2、折半查找
如果数据序列中有N个数据,顺序查找的运算次数是N的数量级,如果N很大,使用顺序查找的代价也相应增大;如果希望大幅度降低运算次数,可以考虑使用折半查找算法。
使用折半查找要求数据序列必须是已经排好序(升序、降序均可)的有序序列。
折半查找(BinarySearch)的查找过程是:
先确定待查关键字所在的范围(区间),然后逐步缩小范围直到找到或找不到该关键字为止。
它先让待查关键值与有序序列中间的一个数据比较,并利用这个中间数据把有序序列划分成一前一后两个子列;如果待查关键值大于中间数据,说明序列中如果存在欲查找的数据,那么这个数据必然保存在后一个子列中,因为只有这个子列中的所有数据都大于中间数据;相反,如果待查关键值小于中间数据,说明欲查找的数据存在于前一个子列中。
这样,通过一次比较,把查找的范围缩小了一半,从整个序列变成一个子列。
同理,继续使用对分方法不断划分更小的子列,缩小查找范围,直至目标子列中只剩余了一个数据;如果这个数据与待查关键值相匹配,则查找成功;否则说明原来的整个数据序列中并不存在一个与待查关键值相匹配的数据,查找失败。
例如,已知一组有序序列如下所示:
现要查找数据63和25。
假设指针low和high分别指示待查元素所在范围的下界和上界,指针mid指示区间的中间位置,即mid=(low+high)/2,在本例中,low和high的初值分别为0及7,mid=7/2=3(取不大于该数的最大整数)。
查找数据63的过程如下:
步骤1:
63>data[3]=45,则low=mid+1=3+1=4,high=7,mid=(4+7)/2=5。
步骤2:
63=data[5],找到数据。
查找数据25的过程如下:
步骤1:
25步骤2:
25步骤3:
25>data[0],则low=mid+1=0+1=1,high=0,因为low>high,所以未能找到数据。
【例6.5】折半查找
/*ProgramnameBSearch.java
一个折半查找的例子
*/
publicclassBSearch{
publicstaticintmax=8;
publicstaticint[]data={13,26,32,45,50,63,75,97};
publicstaticintcounter=1;//计算查找的次数的变量
publicstaticvoidmain(String[]args)
{
for(inti=0;i<8;i++)
System.out.print("["+data[i]+"]");//输出数据
System.out.println("");//换行
if(BinarySearch(63))//查找63
System.out.println("Searchtime="+counter);
else
System.out.println("Thedata63nofound!
");
if(BinarySearch(25))//查找25
System.out.println("Searchtime="+counter);
else
System.out.println("Thedata25nofound!
");
}
publicstaticbooleanBinarySearch(intkey){
intlow;//下界
inthigh;//上界
intmid;//中间位置
low=0;
high=max-1;
while(low<=high)
{
mid=(low+high)/2;
if(keyhigh=mid-1;//查找前半段
elseif(key>data[mid])//待查找值较大
low=mid+1;//查找后半段
elseif(key==data[mid]){//查找到数据
System.out.println("data["+mid+"]="+data[