-
数据结构与算法(七)
顺序/线性查找算法
基本思想:逐一比较数列中的值,找到则返回。
很简单,这里给一个需求:
有一个数列:{1,8, 10, 89, 1000, 1234}
,判断数列中是否包含此名称(顺序查找),要求:如果找到,则输出找到,并给出下标值
/**
* 线性查找
* @param arr 要查找数据的集合
* @param value 要查找的数据
* @return 对应元素的下标,没有找到返回-1
*/
public static int seqSearch(int[] arr,int value){
for(int i = 0; i < arr.length; i++){
if(arr[i] == value){
return i;
}
}
return -1;
}
int[] arr = {1,8, 10, 89, 1000, 1234};
int i = seqSearch(arr, 89);
if(i != -1){
System.out.println("找到对应元素,下标为: " + i);
}else{
System.out.println("没有找到元素");
}
二分查找/折半查找
请对一个 有序数组 进行二分查找 {1,8, 10, 89, 1000, 1234}
,输入一个数看看该数组是否存在此数,并且求出下 标,如果没有就提示「没有这个数」。
二分查找可以使用 递归 和 非递归 实现,本次使用非递归方式实现。
思路分析
查找步骤:
- 首先确定该数组的中间下标
-
然后让需要查找的数(findVal)和
arr[mid]
比较-
findVal > arr[i]
,说明要查找的数在 右 边 -
findVal < arr[i]
,说明要查找的数在 左 边 -
findVal == arr[i]
,说明已经找到,就返回
-
什么时候结束递归?
-
找到则结束递归
-
未找到,则结束递归
当
left > right
时,表示整个数组已经递归完。
代码实现
/**
* 二分查找
* @param arr 要查找数据的有序数组
* @param left 开始查找左边索引
* @param right 开始查找右边索引
* @param findVal 要查找的值
* @return 如果找到返回对应位置的索引,没有找到返回-1
*/
public static int binarySearch(int[] arr,int left,int right,int findVal){
if(left > right){//遍历完没有找到数据
return -1;
}
int mid = (left + right) / 2;
int midVal = arr[mid];
if(findVal > midVal){
//在右边
return binarySearch(arr,mid+1,right,findVal);
}else if(findVal < midVal){
//在左边
return binarySearch(arr,left,mid-1,findVal);
}else{//找到了
return mid;
}
}
上面二分查找只能查找一个值,如果要查找的值有多个值,则不能将其全部返回,对上面代码进行改进:
public static List<Integer> binarySearch2(int[] arr, int left, int right, int findVal){
if(left > right){//遍历完没有找到数据
return new ArrayList<>();
}
int mid = (left + right) / 2;
int midVal = arr[mid];
if(findVal > midVal){
//在右边
return binarySearch2(arr,mid+1,right,findVal);
}else if(findVal < midVal){
//在左边
return binarySearch2(arr,left,mid-1,findVal);
}else{//找到了
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(mid);
int temp = mid -1 ;
while(true){//向左边扫描
if(temp < 0 || findVal != arr[temp]){
break;
}
list.add(temp);
temp -= 1;
}
temp = mid + 1;
while(true){//向右边扫描
if(temp > arr.length-1 || findVal != arr[temp]){
break;
}
list.add(temp);
temp += 1;
}
return list;
}
}
插值查找
查找原理
-
查找查找算法 类似二分查找
不同的是插值查找每次从 自适应 mid 处开始查找
-
将折半查找中求 mid 的索引公式进行改进
- low:表示左边索引
- high:表示右边所以
- key:表示要查找的值
将折半查找中的 二分之一 这个系数进行改写,其他不变。
- 改写后的查找索引求值为int mid = low + (high - low) * (key -arr[low]) / (arr[high] - arr[low])
代码实现
/**
* 插值查找 二分查找的优化
* @param arr 要查找数据的有序数组
* @param left 左边索引
* @param right 右边索引
* @param findVal 要查找的值
* @return
*/
public static int insertSearch(int[] arr,int left,int right,int findVal){
System.out.println("hel");
//findVal < arr[left] || findVal > arr[right]不能省略,否则mid可能出现栈溢出
if(left > right || findVal < arr[left] || findVal > arr[right]){
return -1;
}
int mid = left + (right - left)*(findVal - arr[left])/(arr[right] - arr[left]);
int midVal = arr[mid];
if(midVal < findVal){
return insertSearch(arr,mid+1,right,findVal);
}else if(midVal > findVal){
return insertSearch(arr,left,mid-1,findVal);
}else{
return mid;
}
}
注意事项
- 对于 数据量较大,关键字分布比较均匀 的查找表来说,采用 插值查找,速度较快
- 关键字分布 不均匀 的情况下,该方法不一定比折半查找要好
来源:https://www.cnblogs.com/wyzstudy/p/15408438.html
最新更新
python爬虫及其可视化
使用python爬取豆瓣电影短评评论内容
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
uniapp/H5 获取手机桌面壁纸 (静态壁纸)
[前端] DNS解析与优化
为什么在js中需要添加addEventListener()?
JS模块化系统
js通过Object.defineProperty() 定义和控制对象
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比