public class Search{
/**
*无序表查找:遍历数组
*有序表查找:二分查找,插值查找,斐波拉契查找
*索引查找:分块查找(块间有序,使用二分查找;块内无序,使用顺序查找)
*
*树的查找:二叉排序树
*
*哈希查找:
*/
/**
*有序表查找
*/
//1.二分查找
public int binary_search(int [] a,int key){
int low,mid,high;
low = 0;
high = a.length - 1;
while(low <= high){
mid = low + (high - low)/2;//折半
if(a[mid] == key){
return mid;
}else if(a[mid] < key){
low = mid + 1;
}else{
high = mid - 1;
}
}
return -1;//返回-1代表查找失败
}
//2.插值查找
public int interpolation_search(int [] a,int key){
int low,mid,high;
low = 0;
high = a.length - 1;
while(low <= high){
mid = low + (high - low)*(key - a[low])/(a[high] - key);//插值
if(a[mid] == key){
return mid;
}else if(a[mid] < key){
low = mid + 1;
}else{
high = mid - 1;
}
}
return -1;//返回-1代表查找失败
}
//3.斐波拉契查找
public int fibonacci_search(int [] a,int key){
int low,mid,high;
low = 0;
high = a.length - 1;
int n = a.length;
int k =0;
while(n > f(k) - 1){//计算n位于斐波拉契数列中的位置
k++;
}
//将数组中不满的数值全部补齐,得到数组b
int [] b = new int [f(k) - 1];
for(int i = n;i < f(k) - 1;i++){
b[i] = a[n-1];
}
//斐波拉契查找
while(low <= high){
mid = low + f(k-1) - 1;//计算当前分割的下标
if(a[mid] > key){
high = mid - 1;
k = k - 1;
}else if(a[mid] < key){
low = mid + 1;
k = k - 2;
}else{
if(mid < n) return mid;
else return n - 1;
}
}
return -1;
}
//求斐波拉契数组
public int f(int k){
if(k == 0 || k == 1) return 1;
return f(k-1)+f(k-2);
}
/**
* 散列表(哈希表)查找:在记录的存储位置和它的关键字之间建立一个确定的对应关系f,
* 使得每个关键字key对应一个存储位置f(key),f称为散列函数(哈希函数)。按照这个思路,
* 采用散列技术将记录存储在一块连续的存储空间,这块连续存储空间称为散列表或哈希表。
* 哈希表查找的步骤:
* 1.在存储时,通过散列函数计算记录的散列地址,并按此散列地址存储该记录;
* 2.当查找记录时,通过同样的散列函数计算记录的地址,按此散列地址访问该记录。
*
* 散列函数的构造方法:
* 1.直接定址法:f(key)=a*key+b
* 2.数字分析法
* 3.平方取中(中间的几个数字)法
* 4.折叠法:将关键字从左至右分割成位数相等的几部分(最后一部分位数不够可以短些),然后将这几部分折叠求和,
* 并按散列表表长,取后几位作为散列地址。
* 5.除留余数法:f(key)=key mod p (p<=m),m为表长,p为小于等于m(最好接近m)的最小质数或不包含小于20质因子的合数
* 6.随机数法:f(key)=random(key)
*
* 处理散列冲突的方法:当key1!=key2,f(key1)=f(key2)时,产生冲突
* 1.开放定址法:一旦产生了冲突,就去寻找下一个空的散列地址,
* (1)线性试探法fi(key)=(f(key)+di) mod m (di=1,2,3,...,m-1);
* (2)二次试探法fi(key)=(f(key)+di) mod m (di=1的平方,负1的平方,...,q的平方,负q的平方,q<=m/2);
* (3)随机试探法fi(key)=(f(key)+di) mod m (di是一个随机数列)
* 2.再散列法:fi(key)=RHi(key),RHi是不同的散列函数
* 3.链地址法:将所有关键字为同义词的记录存储在一个单链表中,我们称这种表尾同义词子表,在散列表中只存储同义词子表的头指针
* 4.公共溢出区法:将冲突的记录放在溢出表中。在查找时,对给定值通过散列函数计算出散列地址后,先与基本表的相对应位置进行对比,如果相等,则查找成功;如果不相等,则到溢出表去进行顺序查找。
*/
static int NULLKEY = -32768;//
public static class HashTable{//哈希表结构
int [] elem;//数据元素存储基址
int count; //当前数据元素个数
public HashTable(){
elem=new int [12];
for(int i=0;i<12;i++){
elem[i]=NULLKEY;
}
}
//哈希函数
int hash(int key){
return key % 12;
}
//插入关键字进散列表
void insertHash(HashTable h,int key){
int addr=hash(key);
while(h.elem[addr]!=NULLKEY){//如果不为空,则冲突
addr=(addr+1)%12;//开放定址法的线性试探
}
h.elem[addr]=key; //直到有空位后插入关键字
}
}
//哈希表查找关键字
public static int hash_search(HashTable h,int key){
int addr = h.hash(key);
while(h.elem[addr] != key){
addr = (addr + 1) % 12;
if(h.elem[addr] == NULLKEY || addr == h.hash(key)){
return -1;
}
}
return addr;
}
}
查找算法
最新推荐文章于 2024-10-11 10:58:10 发布