常见的查找算法

查找

查找是在大量的信息中寻找一个特定的信息元素,在计算机应用中,查找是常用的基本运算。

常见的查找算法:

  1. 顺序(线性)查找
  2. 二分查找(折半查找)
  3. 插值查找
  4. 斐波那契查找

1、顺序(线性)查找

顺序查找也称为线形查找,从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败。

代码实现:

package com.xawl.search;

//线性查找
public class SeqSearch {

	public static void main(String[] args) {
		int arr[] = { 1, 9, 11, -1, 34, 89 };// 没有顺序的数组
		int index = seqSearch(arr, -11);
		if(index == -1) {
			System.out.println("没有找到到");
		} else {
			System.out.println("找到,下标为=" + index);
		}
	}
	
	// 线性查找是逐一比对,发现有相同值,就返回下标
	//下面只能找一个目标值,要是想找全部目标值则加入到一个数组中就可以。
	public static int seqSearch(int[] arr, int value) {
		for(int i = 0; i < arr.length; i++){
			if(arr[i] == value){
				return i;
			}
		}java
		return -1;//找不到返回-1
	}
	
}

2、 二分查找(折半查找)重点

二分查找要求线形表中的结点按关键字值升序或降序排列,用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪个子表,这样递归进行,直到查找到或查找结束发现表中没有这样的结点。

代码:

package com.xawl.search;

import java.util.ArrayList;
import java.util.List;

//二分查找(利用递归)
public class BinarySearch {
	public static void main(String[] args) {
		int arr[] = { 1, 8, 10, 89,1000,1000, 1234 };
		
		System.out.println(binarySearch(arr, 0, arr.length-1, 1));
		
//		List<Integer> list = binarySearch2(arr, 0, arr.length-1, 1000);
//		System.out.println(list);
		
	}
	
	/**
	 * 使用二分查找的前提是 该数组是有序的.
	* @Description 
	* @param arr	目标数组
	* @param front	头元素
	* @param rear		尾元素
	* @param findVal	查找值
	* @return	返回目标元素在arr中的索引(只能返回一个)
	 */
	public static int binarySearch(int[] arr, int front, int rear, int findVal) {
		System.out.println("二分查找被调用~");
		//当front > rear时,说明递归整个数组,但是没有找到
		if(front > rear){
			return -1;
		}
		
		int mid = (front + rear)/2;//中间索引
		int midVal = arr[mid];//中间索引对应的值
		
		if(findVal < midVal){//向前递归
			return binarySearch(arr, front, mid-1, findVal);
		}else  if(findVal > midVal){//向后递归
			return binarySearch(arr, mid+1, rear, findVal);
		}else {//找到目标
			return mid;
		}
	}
	
	 // 有多个相同的数值时,如何将所有的数值都查找到?
	/**
	 *  *思路分析
	 * 1. 在找到mid 索引值,不要马上返回
	 * 2. 向mid 索引值的左边扫描,将所有满足的元素的下标,加入到集合ArrayList
	 * 3. 向mid 索引值的右边扫描,将所有满足的元素的下标,加入到集合ArrayList
	 * 4. 将Arraylist返回
	 */
	public static List<Integer> binarySearch2(int[] arr, int front, int rear, int findVal) {
		//当front > rear时,说明递归整个数组,但是没有找到,返回个空数组
		if(front > rear){
			return new ArrayList<Integer>();
		}
		
		int mid = (front + rear)/2;//中间索引
		int midVal = arr[mid];//中间索引对应的值
		
		if(findVal < midVal){//向前递归
			return binarySearch2(arr, front, mid-1, findVal);
		}else  if(findVal > midVal){//向后递归
			return binarySearch2(arr, mid+1, rear, findVal);
		}else {//找到目标
			
			List<Integer> resIndexlist = new ArrayList<Integer>();
			//向前扫描(查看有没有相同的元素)
			int temp = mid -1;
			while(true){
				if (temp<0 || arr[temp] != findVal) {//不符合或者查找完前半部分break;
					break;
				}
				resIndexlist.add(temp);//符合加入到list
				temp --;//前移
			}
			
			resIndexlist.add(mid);//把mid加入
			
			//向后扫描
			temp = mid +1;
			while(true){
				if(temp > arr.length-1 || arr[temp] != findVal){//不符合或者查找完后半部分break;
					break;
				}
				resIndexlist.add(temp);//符合加入到list
				temp ++;//后移
			}
			return resIndexlist;
		}		
	}

	
}

3、插值查找

插值查找算法又称 插值搜索算法 ,是在 二分查找算法 的基础上改进得到的一种查找算法。 插值查找算法只适用于有序序列,换句话说,它只能在升序序列或者降序序列中查找目标元素。 作为“改进版”的二分查找算法,当有序序列中的元素呈现均匀分布时,插值查找算法的查找效率要优于二分查找算法;反之,如果有序序列不满足均匀分布的特征,插值查找算法的查找效率不一定比二分查找算法好。

在这里插入图片描述

代码:

package com.xawl.search;

//插入查找(对二分的优化)
public class InsertValueSearch {

	public static void main(String[] args) {
		int [] arr = new int[100];
		for(int i = 0; i < 100; i++) {
			arr[i] = i + 1;
		}
		
		System.out.println(insertValueSearch(arr, 0, arr.length-1, 2));
	}
	
	/**
	 * 
	* @Description 
	* @param arr 目标数组
	* @param front 头索引	
	* @param rear	尾索引
	* @param findVal 查找值
	* @return	返回目标元素在arr中的索引(只能返回一个)
	 */
	public static int insertValueSearch(int[] arr, int front, int rear, int findVal) { 
		System.out.println("插入查找被调用~");
		//注意:findVal < arr[0]  和  findVal > arr[arr.length - 1] 必须需要
		//否则我们得到的 mid 可能越界
		if(front > rear || findVal < arr[0] || findVal > arr[arr.length - 1]){
			return -1;
		}
		
		// 求出使用自适应取出mid
		int mid = front + (rear - front) * (findVal - arr[front]) / (arr[rear] - arr[front]);
		int midVal = arr[mid];
		
		if(findVal < midVal){//向前递归
			return insertValueSearch(arr, front, mid-1, findVal);
		}else  if(findVal > midVal){//向后递归
			return insertValueSearch(arr, mid+1, rear, findVal);
		}else {//找到目标
			return mid;java
		}
		
	}
}

4、斐波那契查找

斐波那契查找就是在二分查找的基础上根据斐波那契数列进行分割的。 在斐波那契数列找一个等于略大于查找表中元素个数的数F [n],将原查找表扩展为长度为F [n] (如果要补充元素,则补充重复最后一个元素,直到满足F [n]个元素),完成后进行斐波那契分割,即F [n]个元素分割为前半部分F [n-1]个元素,后半部分F [n-2]个元素,找出要查找的元素在那一部分并递归,直到找到。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值