一 查找概论
相关定义:
查找表(Search Table):是由同一类型的数据元素(或记录)构成的集合。
关键字(Key):是数据项中某个数据项的值,又称为键值,用它可以表示一个数据元素。也可以表示一个记录的某个数据项(字段),我们称为关键码。若此关键字可以唯一的标识一个记录,则称此关键字(Primary Key),对于不同的记录,其主关键字均不相同,主关键字所在的数据项称为主关键码。对于那些可以标识多个(或记录)的关键字,我们称为次关键字(Secondary Key),次关键字也可以理解为不以唯一标识一个数据元素(记录)的关键字,它对应的数据项就是次关键码。
查找:就是根据给定的某个值,在查找表中确定一个其主关键字等于给定值的数据元素(或记录)。
查找表的分类: 静态查找表,或者动态查找表。
静态查找表(只做查找操作的查找表)的主要操作是:
(1)查询某个“特定的”元素是否在查找表中。
(2)检索某个“特定的”数据元素和各种属性。
动态查找表:在查找过程中同时插入查找表中不存在 的数据元素,或者从查找表中删除已经存在的某个数据元素,动态查找表的操作主要操作是:
(1)查找的时候插入数据元素。
(2)查找的时候删除数据元素。
二 顺序表查找
1.顺序查找
顺序查找又叫线性查找,是最基本的查找技术,它的查找过程是:从表中的第一个元素开始(或者最后一个元素开始),逐个进行记录的关键字和给定值比较,若某个记录的关键字和给定值相等,则查找成功,找到所查的纪律,如果直到最后一个(或第一个),其关键字和给定值都不相等时,则表中没有所查的记录,查找不成功。
2.顺序表查找算法
class Search{
int sequential_Search(int[] a,int key){
int i;
for(i = 1;i<=a.length();i++){
if(a[i] == key){
return i;
}
}
return 0;
}
}
2.1 顺序查找表的优化
每次循环需要对i是否越界,即是否小于等于n做比较,可以设置一个哨兵,可以解决不需要每次让i与n做判断。
public class SequentialSearch {
/**
* 设置哨兵的顺序表优化
* @param a
* @param n
* @param key
* @return
*/
int sequentialSearch2(int[] a,int n,int key){
int i;
a[0] = key;//将哨兵设置在0处,
i = n;//循环从数组尾部开始
while(a[i] != key){
i--;
}
return i;//返回0则表示查找失败
}
}
2.3 顺序查找表总结:
查找成功最好的情况下就在第一个位置就找到了,算法的时间复杂度就为O(1),最坏的情况下是在最后一个位置才找到,需要n比较,实际复杂度为O(n),查找不成功是需要n+1次比较,时间复杂度为O(n)。关键字在任何一个位置的概率是相同的,所以平均查找次数为(n+1)/2,最终的时间复杂度为n(n)。显然顺序查找技术是有很大的缺点,n很大的时候,查找效率极为低下,优点,这个算法十分的简单,对静态查找表的记录没有任何要求,在一些小型的数据查找时,是可以适用的。另外,也正是由于查找概率的不同,我们完全可以将容易查找的记录放在前面,而不常用的记录放置后面,效率就可以有很大的提升。
三 有序表的查找
3.1 折半查找
折半查找技术,又称为二分查找,它的前提是线性表中的记录必须是关键码有序(通常是从小到大有序),线性表必须采用
顺序存储。折半查找的基本思想是:在有序表中,去中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成
功,若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的
右半区继续查找。不断重复上述过程,知道查找成功,或所有查找区域无记录,查找失败为止。
public class BinarySearch {
public static int binarySerarch(int[] a, int key){
int low,high,mid;
low = 0;
high = a.length-1;
while(low <= high){
mid = (low + high) / 2;
if(key < a[mid]){
high = mid -1;
}else if(key > a[mid]){
low = mid + 1;
}else {
return mid;
}
}
return 0;
}
public static void main(String[] args) {
int[] a = new int[]{0,1,16,24,35,47,59,62,73,88,99};
int i = binarySerarch(a, 62);
System.out.println(i);
}
}
输出:
7
3.2 折半查找总结
对具有n个节点的完全二叉树的深度为log2n +1,向下取整加1,这里虽然折半查找不是完全二叉树,但是同样可以得出
最坏情况是查找到关键字或查找失败的次数为log2n+1;最终折半查找算法的时间复杂度为o(logn)。折半查找的前提条
件是需要有序表顺序存储。