- 实现折半查找的两种方式
//非递归
public static int binarySearch(int a[], int low, int high, int key){
int l = low, h = high, midst;
while(l <= h){
midst = (l + h) / 2;
if(key == a[midst]){
return midst;
}
else if(a[midst] > key){
h = midst - 1;
}
else{
l = midst + 1;
}
}
return -1;
}
// 递归
public static int binarySearchRecur(int a[], int low, int high, int key){
if(low > high) {
return -1;
}
else{
int midst = (low + high) / 2;
if(key == a[midst]){
return midst;
}
else if(a[midst] > key){
return binarySearchRecur(a, low, midst - 1, key);
}
else{
return binarySearchRecur(a, midst + 1, high, key);
}
}
}
而对于midst = (low + high) / 2 的改进如下:
(1) 为避免low+hign溢出 ,可改为 midst = low + 1/2(hign - low);
(2) 对于1/2 的改进: midst = low +[ (key - a[low])/(a[hign] - a[low])]*(hign - low)
这种叫做插值查找 根据要查找的关键字key与查找表中最大最小记录的关键字比较后的查找方法;时间性能同样是logn , 但对于关键字分布均匀的查找表来说,平均性能比二分查找好,但对于【1,3,4,44454,55555,5555】
这种极端数据来说,插值查找不一定合适;
- 二叉排序树的查找
(1)二叉排序树的结构
typedef struct BiTNode{
int data;
struct BiTNode *lchild , *rchild;
}
(2) 二叉排序树的查找实现;
key为查找关键字, 指针f指向T的双亲,若查找成功,则指针p指向该数据元素结点,并返回true ; 否则p指向查找路径上访问的最后一个结点并返回false;
Status SearchBST( BiTNode T , int key , BiTree f , BiTree *p){
if( !T){ //查找不成功
*p = f ;
return false;
}
else if ( key == T -> data){
*p = T;
return true;
}
else if( key < T -> data)
return SearchBST(T -> lchild, key ,T , p);
else
return SearchBST(T -> rchild ,key ,T , p);
}
二叉排序树比较平衡的话,其深度与完全二叉树相同,均为【log2(n)】+1,查找的时间复杂度就为O(logn),等同于折半查找,不平衡的最坏情况下(左斜树,右斜树),时间复杂度为O(n)等同于顺序查找
散列表查找(哈希表)
散列技术即是一种存储方法,又是一种查找方法,最适合查找与给定值相等的记录,不适合范围查找,也不适用于关键字对应多个记录的情况。
冲突:两个关键字key1 ,key2 ,但是f(key1) = f(key2);并把key1和key2称为这个散列函数的同义词。
最常用的散列函数的构造方法是除留余数法
f(key)= key mod p (p<=m) m为散列表长度。
解决冲突的常用办法:
开放定址法:一旦发生冲突就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。(解决冲突的开放定址法称为线性探测法)
fi(key) = (fi(key)+ di)MOD m; di = 1,2,3,4,。。。。,m-1;