查找在实际应用中也是最为常见的。通常我们要在一个集合中查找某一个数或多个数,这个集合称为查找表。查找表分为静态查找表和动态查找表。
静态查找表:在查找表中查询某个“特定的”元素,查找表的大小不会改变,即仅限于查找某个元素,查找表不会被修改。
动态查找表:在查找过程向查找表中删除或插入一个元素,即若在查找过程中同时插入查找表中不存在的元素,或者从查找表中删除已存在的某个元素。
本小节整理的是静态查找表几种典型的查找算法。
1、顺序表的查找
原理:从表中最后一个记录开始,逐个进行记录的关键词与给定值的比较,若某个记录的关键词与给定值相等,则查找成功;反之,若直到第一个记录,其关键词与给定值都不相等,则查找不成功。
算法实现:
int SearchSeq(int arr[],int key){//arr为查找表,key为待查找的元素
for(int i=arr.length-1;arr[i]!=key;--i);
return i;//返回查找表中的下标;若i=-1,则表示没有查找到
}
根据上述算法可知,若查找元素不在查找表中,则需要比较n次,因而运行时间最坏情况是O(n)。
2、折半(判定树、二分查找)查找
原理:对于有序的查找表,可采用折半查找,因为查找表中的元素是有序的,我们可以先确定待查元素所在查找表中的范围,然后逐步缩小查找范围直到找到或找不到为止。
算法的实现:
int SearchBin(int arr[],int key){
int low=0;
int high=arr.length;
while(low<high){
int mid=(low+high)/2;
if(arr[mid]==key) return mid;
else if(arr[mid]>key) high=mid-1;
else low=mid+1;
}
}
例如:已知如下11个数据元素的有序表:
(3,6,7,14,19,24,30,35,56,65,88)
查找元素30。
起始,low指向a[0],high指向a[10],mid=(0+10)/2=5,即mid指向a[5],如图所示:
由于查找元素key=30大于a[mid],所以low=mid+1=6,mid=(6+10)/2=8,再一次进行比较:
此时,查找元素key=30小于a[mid],所以high=mid-1=7,mid=(6+7)/2=6,再一次进行比较:
此时,查找元素key=30等于a[mid],查找成功,返回mid=6。
折半查找每进行一次比较,元素下次查找的范围将缩小为原来的一半,因此查找长度不会超过└ log2n ┘+1,即运行时间最坏情况是O(logn)。
3、静态树表的查找
对于有序表查找,若有序表中各记录的查找概率相等时,折半查找的效率是最优的。若有序表中各记录的查找概率不相等时,则需要建立静态最优查找树。