/**
* 待排序记录类
* @author liangxiamoyi
*
*/
public class Element {
/**
* 数据
*/
private int key;
/**
* 获得数据
* @return key值
*/
public int getKey(){
return key;
}
/**
* 设置数据值
* @param key 数据值
*/
public void setKey(int key){
this.key=key;
}
}
import java.util.Scanner;
/**
* 查找方法类
* @author liangxiamoyi
*
*/
public class Search {
/**
* 顺序查找
* @param r 待查找文件
* @param n 个数
* @param k 查找的元素
* @return 成功返回k所在的位置,不成功返回0
*/
public static int seqSearch(Element[] r,int n,int k){
int i=1;
while(i<=n&&r[i].getKey()!=k){
i++;
}
if(i>n)return 0;
return i;
}
/**
* <p>快速查找,引入一个“虚拟”记录r[n+1],提高算法查找效率</p>
* <p>加速原理:当算法的一个内循环要测试两个或多个条件时,应力图将其减少成一个条件</p>
* <p>算法quickSearch比seqSearch节省20%的运行时间</p>
* @param r 待查找文件
* @param n 个数
* @param k 查找元素
* @return 成功返回k所在的位置,不成功返回0
*/
public static int quickSearch(Element[] r,int n,int k){
int i=1;
r[n+1].setKey(k);
while(r[i].getKey()!=k){
i++;
}
if(i<=n)return i;
return 0;
}
/**
* <p>更快速的查找</p>
* <p>算法quickerSearch比quickSearch总比较次数减少了10%,运行时间减少了30%</p>
* @param r 待查找文件
* @param n 个数
* @param k 查找元素
* @return 成功返回k的位置,不成功返回0
*/
public static int quickerSearch(Element[] r,int n,int k){
int i=-1;
r[n+1].setKey(k);
i+=2;
while(r[i].getKey()!=k){
if(r[i+1].getKey()!=k)i+=2;
else {
i++;
break;
}
}
if(i<=n)return i;
else return 0;
}
/**
* <p>有序表的顺序查找,设定一个虚拟记录r[n+1]=MAX_VALUE</p>
* <p>该算法能更快地确定一个记录不存在</p>
* @param r 待查找的文件
* @param n 个数
* @param k 查找元素
* @return 成功返回k的位置,不成功返回0
*/
public static int sortedSearch(Element[] r,int n,int k){
int i=1;
r[n+1].setKey(Integer.MAX_VALUE);
while(r[i].getKey()<k){
i++;
}
if(r[i].getKey()==k)return i;
else return 0;
}
/**
* 对半查找
* @param r 待查找文件
* @param n 个数
* @param k 查找元素
* @return 成功返回k的位置,不成功返回0
*/
public static int binSearch(Element[] r,int n,int k){
int i,s=1,e=n;
while(s<=e){
i=(s+e)/2;
if(k<r[i].getKey())e=i-1;
if(k>r[i].getKey())s=i+1;
if(k==r[i].getKey())return i;
}
return 0;
}
/**
* 一致对半查找,若n为偶数,则算法有时将涉及一个r[0]=MIN_VALUE
* <p>相比于对半查找,由三个游标变为两个游标</p>
* @param r 待查找文件
* @param n 个数
* @param k 查找元素
* @return 成功返回k的位置,不成功返回0
*/
public static int unanBinSearch(Element[] r,int n,int k){
int i=(n+1)/2;
int m=n/2;
r[0].setKey(Integer.MIN_VALUE);
while(k!=r[i].getKey()){
if(k<r[i].getKey()){
if(m==0)return 0;
else {
i-=(m+1)/2;
m=m/2;
}
}
if(k>r[i].getKey()){
if(m==0)return 0;
else {
i+=(m+1)/2;
m=m/2;
}
}
}
return i;
}
/**
* 计算delta数组
* @param delta 辅助表
* @param n 个数
*/
public static void calDelta(int[] delta,int n){
int k=(int)(Math.log(n)/Math.log(2))+2;
int s=1;//累积存储2的j-1次方,初始为2的0次方,故为1
for(int j=1;j<=k;j++){
delta[j]=(n+s)/(s*2);
s*=2;
}
}
/**
* 使用辅助表的一致对半查找
* <p>该算法和算法unanBinSearch相似,但它使用一个辅助表来代替涉及m的计算</p>
* <p>辅助表的项是DELTA[j]=(N+2^(j-1))/2^j向下取整</p>
* @param r 待查找文件
* @param n 个数
* @param k 查找元素
* @param delta 辅助表
* @return 成功返回k的位置,不成功返回0
*/
public static int conBinSearch(Element[] r,int n,int k,int[] delta){
int i=delta[1],j=2;
while(k!=r[i].getKey()){
if(k<r[i].getKey()){
if(delta[j]==0)return 0;
else {
i-=delta[j];
j++;
}
}
if(k>r[i].getKey()){
if(delta[j]==0)return 0;
else {
i+=delta[j];
j++;
}
}
}
return i;
}
/**
* 构造斐波那契数列
* @param f 存储数列的数组
* @param n 文件个数
*/
public static void fibonacci(int[] f,int n){
f[0]=0;
f[1]=1;
f[2]=1;
int i=2;
while(f[i]<n){
f[i+1]=f[i]+f[i-1];
i=i+1;
}
}
/**
* 斐波那契查找,算法假定n+1是一个斐波那契数,即n+1=f[m+1]
* <p>T(k)表示k阶斐波那契树,若k=0或1则此树就是0;若k>=2;则树T(k)根为f[k].</p>
* <p>左子树为T[k-1],右子树为阶数为k-2且所有结点之编号都增加f[k]的斐波那契树</p>
* @param r 待查找文件
* @param m 个数
* @param k 查找元素
* @param fib 存放Fibonacci序列的数组
* @return 成功返回k的位置,不成功返回0
*/
public static int fibSearch(Element[] r,int m,int k,int[] fib){
int i=fib[m],p=fib[m-1],q=fib[m-2];
int t;
while(k!=r[i].getKey()){
if(k<r[i].getKey()){
if(q==0)return 0;
else {
i-=q;
t=p;
p=q;
q=t-p;
}
}
if(k>r[i].getKey()){
if(p==1)return 0;
else{
i+=q;
p-=q;
q-=p;
}
}
}
return i;
}
/**
* 插值查找,表中关键词已为增序,且在(k[0],k[n+1])之间均匀分布
* @param r 待查找文件
* @param n 个数
* @param k 查找元素
* @return 成功返回k的位置,不成功返回0
*/
public static int interSearch(Element[] r,int n,int k){
int s=0,e=n+1;//s和e表示当前查找子表的下限和上限
int i;
while(e-s>1){
//k的期望值
i=(int)(Math.ceil(s+1.0*(k-r[s].getKey())/(r[e].getKey()-r[s].getKey())*(e-s-1)));
if(k<r[i].getKey())e=i;
if(k>r[i].getKey())s=i;
if(k==r[i].getKey())return i;
}
return 0;
}
public static void main(String[] args){
int num;
Scanner s=new Scanner(System.in);
System.out.println("请输入文件个数:");
num=s.nextInt();
Element[] e=new Element[num+2];
System.out.println("请依次输入文件关键词:");
e[0]=new Element();
e[0].setKey(0);
e[num+1]=new Element();
e[num+1].setKey(13);
for(int i=1;i<num+1;i++){
e[i]=new Element();
e[i].setKey(s.nextInt());
}
System.out.println("请输入你要查找的文件关键词:");
System.out.println(Search.interSearch(e, num, s.nextInt()));
System.out.println(Search.seqSearch(e, num, s.nextInt()));
System.out.println(Search.quickSearch(e, num, s.nextInt()));
System.out.println(Search.quickerSearch(e, num, s.nextInt()));
System.out.println(Search.sortedSearch(e, num, s.nextInt()));
System.out.println(Search.binSearch(e, num, s.nextInt()));
System.out.println(Search.unanBinSearch(e, num, s.nextInt()));
int[] delta=new int[num];
Search.calDelta(delta, num);
System.out.println(Search.conBinSearch(e, num, s.nextInt(), delta));
int[] fib=new int[num];
Search.fibonacci(fib, num);
int m=0;
while(fib[m+1]-1!=num){
m++;
}
System.out.println(Search.fibSearch(e, m, s.nextInt(), fib));
}
}
测试结果: