顺序查找
原理
对于任意一个序列以及一个给定的元素,将给定元素与序列中元素依次比较,直到找出与给定关键字相同的元素,或者将序列中的元素与其都比较完为止。
代码实现
//顺序查找代码实现 找到一个满足的值就返回
public class SeqSearch {
public static void main(String[] args) {
int[] arr ={12,9,-9,78};
int index=sequenceSearch(arr,-9);
if (index==-1){
System.out.println("没有找到");
}else {
System.out.println("找到了下标为"+index);
}
}
public static int sequenceSearch(int[] arr, int value) {
//遍历数组查找
for (int i = 0; i < arr.length; i++) {
//如果找到,返回下标
if (arr[i] == value) {
return i;
}
}
//如果未找到,返回-1
return -1;
}
}
运行结果
算法分析
优点:
- 对待查序列(表)无要求 —— 待查找序列可以是有序,也可以是无序;
- 从第一个元素开始;
- 需要逐一遍历整个待查序列(除非已经找到);
- 若查找到最后一个元素还没找到,则查找失败;
缺点: - 效率低 —— 需要遍历整个待查序列
时间复杂度:
O(n),平均查找时间 = 列表长度/2
空间复杂度:
1个待查序列+1个目标元素 <=> O(n)
二分查找
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
原理分析
- 首先确定该数组的中间的下标
mid= (left +right) / 2
。 - 然后让需要查找的数value和arr[mid]比较。
- value>arr[mid],说明你要查找的数在mid的右边,因此需要递归的向右查找。
- value<arr[mid],说明你要查找的数在mid的左边,因此需要递归的向左查找。
- value ==arr[mid]说明找到,就返回。
什么时候我们需要结束递归?
1)找到就结束递归。
2)递归完整个数组,仍然没有找到value,也需要结束递归当left> right就需要退出。
代码实现
//二分查找:前提该数组有序
public class BinarySearch {
public static void main(String[] args) {
//定义一个数组
int [] arr={-3,2,34,67,88,199};
int resultIndex = binarySearch(arr, 0, arr.length - 1, 1111111);
if (resultIndex==-1){
System.out.println("寻找的值在数组中不存在");
}else {
System.out.println("找到了下标为" + resultIndex);
}
}
//left 左边索引 right 右边索引 value 要查找的值
public static int binarySearch(int []arr,int left,int right,int value){
//递归完整个数组,仍然没有找到value,也需要结束递归当left> right就需要退出。
if(left>right){
return -1;
}
//先拿到中间索引和值
int mid=(left+right)/2;
int midValue=arr[mid];
if(value>midValue){
//向右递归
return binarySearch(arr,mid+1,right,value);
}else if(value<midValue){
//向左递归
return binarySearch(arr,left,mid-1,value);
}else {
return mid;
}
}
}
运行结果
算法分析
优点
- 比较次数少,查找速度快,平均性能好;
缺点
- 要求待查表为有序表,且插入删除困难。
因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
时间复杂度:
- 最坏的情况下两种方式时间复杂度一样:O(log2 N)
- 最好情况下为O(1)
空间复杂度:
-
非递归方式:由于辅助空间是常数级别的所以:空间复杂度是O(1);
-
递归方式:递归的次数和深度都是log2 N,每次所需要的辅助空间都是常数级别的:
空间复杂度:O(log2N )