在学习之前我们先来了解一下什么是查找。
所谓查找,就是在一组数据中判断元素是否存在,或返回元素及其位置。查找的场景分两类,一类是在无序列表中进行查找,另一类是在有序列表中进行查找。
一、无序查找
无序查找就是顺序查找这组数据(无序数组)中的每个元素,判断要查找的数据元素是否存在。如果查找成功,则返回该yua元素在数据组中的位置,若查找失败,则返回-1,其实我们了解了这个无序查找,那么代码就是小意思了。代码实现如下:
public class SeqSearch {
public static int seqSearch(int[] a, int elem) {
int n = a.length;
int i = 0;
while (i < n && a[i] != elem) {
i++; // 逐个对比,不相同则数组下标数加1
}
if (i == n) { // 数组下标数等于数组长度说明没查到指定元素
return -1;
} else {
return i + 1; //如果找到了就返回数组的下标+1
}
}
public static void main(String[] args) {
int[] test = { 123, 456, 789, 234, 567, 890, 345, 678, 901, 33 };
int elem = 33;
int res = seqSearch(test, elem);
if (res != -1) {
System.out.println("查找成功!该元素为第:" + res + "个元素");
} else {
System.out.println("查找失败!该元素在数据组中不存在!");
}
}
二、有序查找(二分查找)
上面是在一个无序的数据组中进行查找,使用了逐个比对的方法。假设现在需要在一个有序的数据组中进行查找,例如,上面案例的数据test在查找前已经进行了排序,在数组中按照升序进行了排列,难道还用逐个比对的方法进行查找吗?答案是否定的。这时候二分查找就能发挥作用了。
public class zheban {
public static int biSearch(int[] a, int elem) {
int n = a.length;
// 定义低位下标、高位下标、中间位下标
int low = 0, high = n - 1, mid;
// 二分查找
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 = { 123, 456, 789, 234, 567, 890, 345, 678, 901, 33 };
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("查找失败!该元素在数据组中不存在!");
}
}
总结:
二分查找又称折半查找,优点是bi'j比较次数少,查找速度快,平均性能好,缺点是要求待查数据结构为有序数据结构,且插入、删除困难。因此,二分查找适用于数据不经常变动而查询频繁的有序数据结构。
假设数据结构中元素是按升序排列的,将数据结构中间位置记录的数据与要查找数据进行比较,如果两者相等,则查找成功;否则利用中间位置将数据结构分成前、后两个子数据结构,如果中间位置记录的数据大于要查找的数据,则进一步查找前一子数据结构,否则进一步查找后一子数据结构。重复以上过程,直到找到满足条件的数据,则查找成功,或直到子数据结构不存在为止,此时查找不成功。