查找的基本概念
1)查找:在数据集合中寻找满足某种条件的数据元素的过程成为查找。查找的结果一般分为两种:查找成功,即在数据集合中找到了满足条件的数据元素;另一种是查找失败。
2)查找表(查找结构):用于查找的数据集合称为查找表,它由同一种类型的数据元素(或者记录)组成,可以使一个数组或链表等数据类型。对查找表经常进行的操作一般有四种:①查询某个特定的数据元素是否在查找表中;②检索满足条件的某个特定的数据元素的各种属性;③在查找表中插入一个数据元素;④从查找表中删除某个数据元素。
3)静态查找表:如果一个查找表的操作是设计①和②的操作,则无需动态地修改查找表,此类查找表称为静态查找表。与此对应,需要动态地插入或者删除的查找表则称为动态查找表。适合静态查找表的方法有:顺序比较,折半查找,散列查找等。二叉平衡数和B树都是二叉排序树的改进。
4)关键字:数据元素中唯一标识该元素的某个数据项的值,使用基于关键字的查找,查找结果应该是唯一的。比如由一个学生元素构成的数据集合,则学生元素中“学号”这一数据项的值唯一表示一个学生。
5)平均查找长度:在查找的过程中,一次查找的长度是指需要比较的关键字次数,而平均查找长度则是指所有查找过程中进行关键字的比较次数的平均值。平均查找长度是衡量查找算法效率的最主要的指标。
- 顺序查找
概念:顺序查找又称为线性查找,主要用于在线性表中进行查汇总啊。顺序查找通常分为对一般的无序线性表的顺序查找和对按关键字的有序的顺序查找。
- 一般的线性表的顺序查找
思想:作为一种最直观的查找方法,其基本思想是从线性表的一端开始,逐个检查关键字是否满足给定的条件。若查找到某个元素的关键字满足给定条件,则查找成功,返回该元素在线性表中的位置;若已经查到表的另一端,还没有查找到符合给定条件的元素,则返回查找失败的信息。
- 有序表的顺序查找
概念:如果在查找之前就已经知道了表示按关键字有序的,那么查找失败时可以不用再比较到表的另一端就能返回查找失败的信息,这样能降低顺序查找失败的平均查找长度。
思想:假设表L是按关键字从小到大排列的,查找的顺序是从前往后查找,待查找元素关键字为key,当查找到第i个元素时,发现第i个元素对应的关键字小于key,但第i+1个圆度对应的关键字大于key,这时就可以返回查找失败的信息了,因为第i个元素之后的元素的关键字均大于key,所以表中不存在关键字为key的元素。
- java代码实现顺序查找:
import java.util.Scanner;
/**
* @author:cch
* @description:顺序查找
* @date 2020/12/23
*/
public class MySequentialSearch {
public static void main(String[] args) {
int a[]={6,11,23,9,15,78,66,17};
Scanner sc1=new Scanner(System.in);
int keytype1=sc1.nextInt();
System.out.println("关键字在第"+seqsearch(st1,keytype1)+"个位置");
}
public static int seqsearch(int[]a,int keytype){
if(a.length>0){
for(int i=0;i<a.length;i++){
if(a[i]==keytype) //若查找成功,则返回元素下标i
return i;
}
}
return -1; //若查找不成功,返回-1;
}
}
- 折半查找
概念:折半查找又称为二分查找,它仅适用于有序的顺序表。
思想:首先将给定值的key与表中中间位置元素的关键字比较,若相等,则查找成功,返回该元素的存储位置;若不等,则所需查找的元素只能在中间元素以外的前半部分或后半部分中(例如,在查找升序排列时,若给定值key大于中间元素的关键字,则所查找的元素只可能在后半部分)。然后在缩小范围你继续进行同样的查找,如此重复直到找到为止,或者确定表中没有所需要的查找的元素,则查找不成功,返回失败的信息。
- java代码实现:
import java.util.Arrays;
/**
* @author:cch
* @description:折半查找
* @date 2020/12/23
*/
public class HalfSearch {
public static int biSearch(int[] a, int elem) {
int n = a.length;
// 定义低位下标、高位下标、中间位下标
int low = 0;
int high = n - 1;
int mid = 0 ;
// 二分查找
while (low <= high) {
mid = (low + high) / 2;
System.out.println(a[mid]);
if (a[mid] == elem) {
/**
* 如果两者相等,则查找成功; 否则利用中间位置的记录
* 将数据结构分成前、后两个子数据结构,
* 如果中间位置记录的数据大于要查找的数据,则进一步查找前一子数据结构,
* 否则进一步查找后一子数据结构。
*/
return mid + 1; // 返回数组的下标+1
} else if (a[mid] < elem) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
public static void main(String[] args) {
int[] test = { 23, 15,9, 11, 520, 998, 216, 789, 601, 35 };
Arrays.sort(test);
System.out.println(Arrays.toString(test));
int elem = 111;
int res = biSearch(test, elem);
if (res != -1) {
System.out.println("查找成功!该元素为第:" + res + "个元素");
} else {
System.out.println("查找失败!该元素在数据组中不存在!");
}
}
- 分块查找
概念:分快查找又称为索引顺序查找,吸取了顺序查找和折半查找各自的有点,既有动态结构,又适于快速查找。
思想:将查找表分为若干个子块。块内的元素可以无序,但块之间是有序的,即第一个块中的最大关键字小于第二个块中的所有记录的关键字,第二个块中的最大关键字小于第三个块中的所有记录的关键字,以此类推。再建立一个索引表,索引表中的每个元素含有各块的最大关键字和各个块的第一个元素的地址,索引表按关键字有序排列。块内是无序的,块间是有序的,例如块2中最大元素小于块3中最小元素。
分块查找的过程分为两步:第一步在索引表中确定待查找记录所在的块,可以顺序查找或折半查找索引表;第二步在块内顺序查找。
先用二分查找索引表,确定需要查找的关键字在哪一块,然后再在相应的块内用顺序查找。分块查找又称为索引顺序查找。
下图所示为一个索引顺序表。
其中包括三个块,第一个块的起始地址为 0,块内最大关键字为25;
第二个块的起始地址为 6,块内最大关键字为 55;
第三个块的起始地址为9,块内最大关键字为 70。
第三个块的起始地址为13,块内最大关键字为 98。
分块查找的基本过程如下:
(1)首先,将待查关键字 K 与索引表中的关键字进行比较,以确定待查记录所在的
块。具体的可用顺序查找法或折半查找法进行。
(2)进一步用顺序查找法,在相应块内查找关键字为 K的元素。
java代码实现:
import java.util.Arrays;
/**
* @author:cch
* @description:折半查找
* @date 2020/12/23
*/
public class HalfSearch {
//index代表索引数组,st2代表待查找数组,keytype代表要查找的元素,m代表每块大小
public static int blocksearch(int[] index,int[]st2,int keytype,int m){
int i=shunxusearch(index,keytype); //shunxunsearch函数返回值为带查找元素在第几块
System.out.println("在第"+i+"块");
if(i>=0){
int j=m*i; //j为第i块的第一个元素下标
int curlen=(i+1)*m;
for(;j<curlen;j++){
if(st2[j]==keytype)
return j;
}
}
return -1;
}
public static void main(String args[]){
int index[]={25,55,78};
int st2[]={25, 10, 23, 6, 7, 20, 33, 41, 42, 38, 51, 55, 59, 61, 78, 80, 76, 83};
System.out.println(blocksearch(index,st2,55,6));
}
}