查找算法-分块查找,哈希查找

分块查找

    先选取各块中的最大关键字构成一个索引表;

    查找分两个部分:先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中;然后,在已确定的块中用顺序法进行查找。

    时间复杂度为O(log2m+N/m),m为分块的数量,N为主表元素的数量,N/m 就是每块内元素的数量。

    举例:例如学号这个问题,一般来说学号的前几位代表年级和学院,例如19030111,19030123,18023123,18023555......,19代表19级,030代表计科院,18代表18级,023代表机电院,我们可以选取学号前5位为最大关键字,按照前五位将以学号为键值的数据分块存储,当我们需要一个学号对应的信息时,我们首先对最大键值二分查找,查出此学号对应的数据块,然后对数据块顺序查找。

    优缺点:分块查找的特点其实显而易见,那就是分块查找拥有顺序查找和二分查找的双重优势,即顺序查找不需要有序,二分查找的速度快。分块查找由于只需要索引表有序,所以特别适合用于在动态变化的数据元素序列中查找。但是如何分块比较复杂。如果分块过于稀疏,则可能导致每一块的内容过多,在顺序查找时效率很低;如果分块过密,则又会导致块数很多,无论是插入还是删除数据,都会频繁地进行二分查找;如果块数特别多,则基本上和直接二分查找的动态插入数据类似,这样分块查找就没有意义了。

    代码:就是将二分查找和顺序查找拼接,这里不再赘述。

哈希查找

    通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。

    算法流程:

    1. 用给定的哈希函数构造哈希表;

    2. 根据选择的冲突处理方法解决地址冲突,常见的解决冲突的方法:拉链法和线性探测法。
 
冲突解决方法:
    开放定址法
    开放定址法是一类以发生冲突的哈希地址为自变量,通过某种哈希冲突函数得到一个新的空闲的哈希地址的方法。
    (1)线性探测法
        线性探测法是从发生冲突的地址(设为d)开始,依次探测d的下一个地址(当到达下标为m-1的哈希表表尾时,下一个探测的地址是表首地址0),直到找到一个空闲单元为止(当m≥n时一定能找到一个       空闲单元)。线性探测法的数学递推描述公式为:
                                       d0=h(k)
                                       di=(di-1+1) mod m(1≤i≤m-1)
代码(Java):
package search;


public class hash 
{
    static int hash_1(int arrLeng,int value)
    {
        return value % arrLeng;
    }
    public static int hash_search(int [] hashArr,int value) 
    {
        int length = hashArr.length;
        int hashAdd = hash_1(length,value);
        while (hashArr[hashAdd] != value) 
        {   
            hashAdd = (hashAdd + 1) % length;     
            if (hashArr[hashAdd] == -1 || hashAdd == hash_1(length,value)) 
            {
                return -1;
            }
        }
        return  hashAdd;
    }
    public static void main(String[] args) 
    {
        int[] hashArr = new int[] {77,44,-1,-1,26,93,17,-1,-1,31,54};
        int hashAdd = hash_search(hashArr,77);
        if(hashAdd == -1) 
        {
            System.out.println("fail");
        }
        else 
        {
            System.out.println("index = " + hashAdd);
        }
    }
}
(2)平方探测法
         平方探测法的数学描述公式为:
                                  d0=h(k)
                              di=(di-1+i2)modm (1≤i≤m-1)
         平方探测法是一种较好的处理冲突的方法,可以避免出现堆积问题。
         它的缺点是不能探测到哈希表上的所有单元,但至少能探测到一半单元。
 
    拉链法
    拉链法是把所有的同义词用单链表链接起来的方法。在这种方法中,哈希表每个单元中存放的不再是记录本身,而是相应同义词单链表的头指针。

 

 

 实现方法:可以自己编写,也可以直接调用Java的hashmap实现。

import java.util.HashMap;

public class RunoobTest {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        System.out.println(Sites.get(3));
    }
}

 

posted @ 2022-04-27 16:57  嗯嗯魑嗯嗯  阅读(589)  评论(0编辑  收藏  举报