Java 查找算法

这个问题有几个点要先确认

  • 必须是有序,如果无序的话就只能全遍历了
  • 查找算法跟数据结构相关,不同的数据结构适用于不同的查找算法
  • 查找算法与磁盘I/O有一定的关系,比如数据库在索引排序的时候,如果每次都从磁盘读取一个节点然后进行判断

数组

如果知道下标的话就方便了,查找的复杂度为1.
如果是针对值的查找,那么顺序遍历是O(n),

二分查找

使用二分查找的话可以减少时间复杂度为:O(logn)

/**
 * 二分查找又称折半查找,它是一种效率较高的查找方法。
  【二分查找要求】:1.必须采用顺序存储结构 2.必须按关键字大小有序排列。
 * @author wzj
 *
 */
public class BinarySearch {
    public static void main(String[] args) {
        int[] src = new int[] {1, 3, 5, 7, 8, 9};
        System.out.println(binarySearch(src, 3));
        System.out.println(binarySearch(src,3,0,src.length-1));
    }

    /**
     * * 二分查找算法 * *
     *
     * @param srcArray
     *            有序数组 *
     * @param des
     *            查找元素 *
     * @return des的数组下标,没找到返回-1
     */
   public static int binarySearch(int[] srcArray, int des){ 

        int low = 0;
        int high = srcArray.length-1;
        while(low <= high) {
            int middle = (low + high)/2;
            if(des == srcArray[middle]) {
                return middle;
            }else if(des <srcArray[middle]) {
                high = middle - 1;
            }else {
                low = middle + 1;
            }
        }
        return -1;
   }

      /**
     *二分查找特定整数在整型数组中的位置(递归)
     *@paramdataset
     *@paramdata
     *@parambeginIndex
     *@paramendIndex
     *@returnindex
     */
    public static int binarySearch(int[] dataset,int data,int beginIndex,int endIndex){
       int midIndex = (beginIndex+endIndex)/2;
       if(data <dataset[beginIndex]||data>dataset[endIndex]||beginIndex>endIndex){
           return -1;
       }
       if(data <dataset[midIndex]){
           return binarySearch(dataset,data,beginIndex,midIndex-1);
       }else if(data>dataset[midIndex]){
           return binarySearch(dataset,data,midIndex+1,endIndex);
       }else {
           return midIndex;
       }
   }
}

但是插入因为会涉及当前节点后的所有值得移动,一次,其时间复杂度为O(n) + O(log n)

链表

只能从头节点遍历, 查找的复杂度是O(n)
插入或者是删除,因为只需要移动指针,时间复杂度为O(1) + O(n)

树的查找,主要是先序遍历,中序等遍历方式。
插入和删除,还是比较快
常用的会有如下的衍生方式:

二叉树

二叉树的构建:

class BinaryNode{
        int value;
        BinaryNode left;
        BinaryNode right;
        public BinaryNode(int value){
            this.value = value;
            this.left = null;
            this.right = null;
        }

        public void add(int value){
            if(value > this.value){
                if(this.right != null){
                    this.right.add(value);
                }else{
                    this.right = new BinaryNode(value);
                }
            }else{
                if(this.left != null){
                    this.left.add(value);
                }else{
                    this.left = new BinaryNode(value);
                }
            }
        }

        // 中序查找
        public BinaryNode get(int value){
            if(this.value == value){
                return this;
            }
            if(this.value > value){
                return this.left.get(value);
            }

            if(this.value < value){
                return this.right.get(value);
            }
            return null;
        }
    }

插入的复杂度本身并不高,只是简单的节点添加。但是因为寻找插入位置的查找操作的复杂度跟树的高度相关为logn,极差的情况下可能接近于线性查找。

平衡二叉树

平衡二叉树是尽量减少数高的二叉树,其算法中增加了左旋和右旋的操作。插入复杂度会高一些,但是会得到不错的查找性能。

B+Tree

学习自这里
这个就要说一下上面说的跟磁盘I/O相关的,因此为了减少磁盘I/O。可以利用磁盘的预读特性,一次提取大概相当于一页大小的节点到内存中。
先要说一下B-Tree.
一个平衡的m-way查找数,其要满足如下的条件:

  • 每节点中的数据量 < m
  • 每层节点数 <= m
  • 子数节点要完全大于、小于、或者在其之间。 也就是不能越过父节点的两个值
  • 叶子节点中的值的个数>=m/2
  • 非叶子节点中的值的个数=子节点个数-1
    如下图:

    可以看出,三个子节点的有两个值,三个子节点中的数据分别对应了小于、之间、大于这个范围

B+Tree
与上面的差别是:

  • 所有关键字都在叶子节点
  • 父节点存储的都是到子节点的指针
  • 会有两个入口,一个是根节点,另外一个是从最小叶子节点开始的指针

查找跟二叉树比较像,因为插入的时候已经是相当于二分算法了,所以只需要,递归找到就可以了。

Hash表

为了解决一些不容易排序,或者查找的对象。 比如图像,视频等等。
在Java的HashMap中有使用。
是一个链表的数组
- 对key进行进行散列函数,求Hash值,找到其对应的链表。
- 剩下的解决hash冲突的问题
- 解决hash冲突,可以在命中链表之后顺序比较
- 这里顺便再说一下一致性hash. 预置很多节点,选择最近的节点存入,可以解决增加节点数据转移的问题。

时间: 2024-08-01 19:51:24

Java 查找算法的相关文章

Java实现二分法查找算法

[ 什么是二分查找 ] 二分查找又称为折半查找,该算法的思想是将数列按序排列,采用跳跃式方法进行查找,即先以有序数列的中点位置为比较对象, 如果要找的元素值小于该中点元素,则将待查序列缩小为左半部分,否则为右半部分.以此类推不断缩小搜索范围. [ 二分查找的条件 ] 二分查找的先决条件是查找的数列必须是有序的. [ 二分查找的优缺点 ] 优点:比较次数少,查找速度快,平均性能好: 缺点:要求待查数列为有序,且插入删除困难: 适用场景:不经常变动而查找频繁的有序列表. [ 算法步骤描述 ] ① 首

Java实现二分查找算法实例分析_java

本文实例讲述了Java实现二分查找算法.分享给大家供大家参考.具体如下: 1. 前提:二分查找的前提是需要查找的数组必须是已排序的,我们这里的实现默认为升序 2. 原理:将数组分为三部分,依次是中值(所谓的中值就是数组中间位置的那个值)前,中值,中值后:将要查找的值和数组的中值进行比较,若小于中值则在中值前面找,若大于中值则在中值后面找,等于中值时直接返回.然后依次是一个递归过程,将前半部分或者后半部分继续分解为三部分.可能描述得不是很清楚,若是不理解可以去网上找.从描述上就可以看出这个算法适合

基于Hash的查找算法实现

package da; public class MyMap< K, V> { private int size;// 当前容量 private static int INIT_CAPACITY = 16;// 默认容量 private Entry< K, V>[] container;// 实际存储数据的数组对象 private static float LOAD_FACTOR = 0.75f;// 装载因子 private int max;// 能存的最大的数=capacity

Java排序算法总结之插入排序_java

本文实例讲述了Java插入排序方法.分享给大家供大家参考.具体分析如下: 有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到插入排序法.本文主要介绍的是插入排序的java实现.   插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据.比较和交换的时间复杂度为O(n^2),算法自适应,对于数据已基本有序的情况,时间复杂度为O(n),算法稳定,开销很低.算法适合于数据已基本有序或者数据量

Java抽奖算法第二例_java

本文实例为大家分享了java抽奖算法,供大家参考,具体内容如下 1. 算法分析 根据概率将奖品划分区间,每个区间代表一个奖品,然后抽取随机数,反查落在那个区间上,即为所抽取的奖品.  2. 代码核心算法  public class Arithmetic { // 放大倍数 private static final int mulriple = 1000000; public int pay(List<Prize> prizes) { int lastScope = 0; // 洗牌,打乱奖品次

一个经典的二分查找算法的Bug

1:     binarySearch([] a, key) {2:         low = 0;3:         high = a.length - 1;4: 5:         (low <= high) {6:             mid = (low + high) / 2;7:             midVal = a[mid];8:9:             (midVal < key)10:                 low = mid + 1;11: 

Ruby实现二分搜索(二分查找)算法的简单示例_ruby专题

在计算机科学中,二分搜索(英语:binary search),也称折半搜索(英语:half-interval search).对数搜索(英语:logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法.搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束:如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较.如果在某一步骤数组为空,则代表找不到.这种搜索算法每一次比较都使搜索范围缩小一半

二分查找算法在C/C++程序中的应用示例_C 语言

 二分查找算法的思想很简单,<编程珠玑>中的描述: 在一个包含t的数组内,二分查找通过对范围的跟综来解决问题.开始时,范围就是整个数组.通过将范围中间的元素与t比较并丢弃一半范围,范围就被缩小.这个过程一直持续,直到在t被发现,或者那个能够包含t的范围已成为空.         Donald Knuth在他的<Sorting and Searching>一书中指出,尽管第一个二分查找算法早在1946年就被发表,但第一个没有bug的二分查找算法却是在12年后才被发表出来.其中常见的一

JavaScript使用二分查找算法在数组中查找数据的方法_javascript技巧

本文实例讲述了JavaScript使用二分查找算法在数组中查找数据的方法.分享给大家供大家参考.具体分析如下: 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一