哈希表的构建与查询

(本文内容来自互联网)

11.2 哈希函数构造方法

设要存放的数据元素有n个,存放数据元素的数组个数为m,哈希函数的设计目标,就是要使通过哈希函数得到的n个数据元素的哈希地址 。

1 除留余数法

除留余数法是用数据元素的关键字K除以哈希表长度m所得的余数作为哈希地址的方法。除留余数法的哈希函数h(K)为:

h(K) = K mod m

11.3 哈希冲突解决方法

解决哈希冲突的方法主要有开放定址法和链表法两大类。 开放定址法

开放定址法是一类以发生哈希冲突的哈希地址为自变量、通过某种哈希冲突函数得到一个新的空闲的哈希地址的方法。开放定址法的哈希冲突函数通常是一组。

1 线性探查法

线性探查法是从发生哈希冲突的地址d开始,依次探查d的下一个地址,直到找到一个空闲单元为止。线性探查法的数学递推描述公式为:

如下哈希表类的哈希函数采用除留余数法,   哈希冲突函数采用开放定址法中的线性探查法。

package cn.ls.hash;

public class HashItem {
	int data=0;
    int info=0;//标志:0表示空闲状态,1表示占用状态.  

    HashItem(int i) {
        info = i;
    }  

    HashItem(int d, int i) {
        data = d;
        info = i;
    }
}
package cn.ls.hash;

public class HashTable {
	 private HashItem[] ht; // 哈希表数组
	    private int tableSize; // 哈希表的长度
	    private int currentSize; // 当前的表项个数  

	    HashTable(int m) { // 构造函数
	        tableSize = m;
	        ht = new HashItem[tableSize];
	        currentSize = 0;
	    }  

	    public boolean isIn(int x) { // x是否已存在
	        int i = find(x);
	        if (i >= 0)
	            return true;
	        else
	            return false;
	    }  

	    public int getValue(int i) { // 取数据元素值
	        return ht[i].data;
	    }  

	    public int find(int x) { // 查找
	        int i = x % tableSize;
	        int j = i;  

	        if (ht[j] == null)
	            ht[j] = new HashItem(0);//设置info标记为0
	        //注意要加上非空判断.
	        while (ht[j] != null && ht[j].info == 1 && ht[j].data != x) { // 说明存在冲突
	            j = (j + 1) % tableSize; // 得到下一个哈希地址
	            if (j == i)
	                return -tableSize;
	            // 若j == i表示已查找完了整个哈希表的数组,返回- tableSize
	        }
	        if (ht[j] != null && ht[j].info == 1) //此条件成立表示查找到
	            return j; // 返回该数据元素的下标
	        else
	            //此时表示没有查找到  返回该数据元素哈希地址的负值
	            return -j;
	    }  

	    public void insert(int x) throws Exception { // 插入
	        int i = find(x); // 查找x 是否已存在,并返回数组下标  

	        if (i > 0) { // 如果x存在
	            throw new Exception("该数据已存在");
	        }  

	        else if (i != -tableSize) { // 如果x不存在
	            ht[-i] = new HashItem(x, 1); //插入数据元素x,并设置info标记为1
	            currentSize++; // 当前元素个数加1
	        } else { // 如果i等于-tableSize,表示哈希表已满
	            throw new Exception("哈希表已满无法插入");
	        }
	    }  

	    public void delete(int x) throws Exception { // 删除
	        int i = find(x); // 查找x 是否已存在,并返回数组下标  

	        if (i >= 0) { // 如果x存在
	            ht[i].info = 0; // 置为空闲状态
	            currentSize--; // 当前元素个数减1
	        } else { // 如果x不存在
	            throw new Exception("该数据不存在");
	        }
	    }
}
package cn.ls.hash;

public class Exam11_3 {
	public static void main(String[] args) {
        //7个数据元素,哈希表数组个数取11进行测试。
        HashTable myHashTable = new HashTable(11);
        int[] a = { 180, 750, 600, 430, 541, 900, 460 };
        int i, j, n = 7, item;  

        try {
            for (i = 0; i < n; i++)
                myHashTable.insert(a[i]);  

            for (i = 0; i < n; i++) {
                j = myHashTable.find(a[i]);
                if (j > 0) {
                    item = myHashTable.getValue(j);
                    System.out.println("j = " + j + "  ht[] = " + item);
                }
            }  

            if (myHashTable.isIn(430))
                System.out.println("数据元素430在哈希表中");
            else
                System.out.println("数据元素430不在哈希表中");  

            myHashTable.delete(430);
            if (myHashTable.isIn(430))
                System.out.println("数据元素430在哈希表中");
            else
                System.out.println("数据元素430不在哈希表中");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

测试结果:

j = 4  ht[] = 180

j = 2  ht[] = 750

j = 6  ht[] = 600

j = 1  ht[] = 430

j = 3  ht[] = 541

j = 9  ht[] = 900

j = 10  ht[] = 460

数据元素430在哈希表中

数据元素430不在哈希表中

时间: 2024-08-11 00:53:37

哈希表的构建与查询的相关文章

哈希表的应用

哈希表又叫做散列表,是一种高效的数据结构,其高效主要体现在把数据的存储和查找时间大大降低,几乎可以看成是常数时间,而代价是消耗比较多的内存,然而在硬件技术越来越发达的今天,用空间换时间的做法在某种意义上是值得的.另外,编码比较容易也是它的特点之一. 什么时候适合应用哈希表呢?综合国内外实际应用情况,可以概括为:高效的数据存储和查找均可以用哈希表. 下面就目前有关哈希表流行的应用做一些初步的探讨. 1.对等网络(P2P)中的应用 a) 基于分布式哈希表的系统 对于对等计算系统而言,能够适应的网络规

哈希表的基本操作

散列(hash)表/哈希表 1.关键字和和存储的地址建立一个对应的关系:Add = Hash(key): 2. 解决冲突方法: (1)开放定址法 – 探测方式:线性探测.二次探测. (2)再哈希法 (3)分离链接法 – 利用链表的方式. (4)公共溢出区法 3.存储结构:用顺序存储来构建哈希表.构建结构数组 注意:使用不同的哈希函数得到的冲突次数不同. ---------------------------------------------------------------------- 除

Python算法教程第二章知识点:计时模块、字典与散哈希表、图与树的实现、成员查询、插入对象

本文目录:一.计时模块:二.字典与散哈希表:三.图与树的实现:四.成员查询:五.插入对象</br>一.计时模块(timeit.cProfile) import timeit timeit.timeit('x = 1 + 2') 既然学习算法,那么来计算程序所耗费的时间是重要的,但是需要注意:timeit()计时函数会多次运行相关的代码段并求得平均值,以提高计时的精准度,所以,我们需要预防早先的执行操作影响之后代码的执行.举个栗子:若我们执行排序算法,则只有第一次执行代码时是在随机的情况下计时,

c语言构建哈希表

/*哈希查找 *哈希函数的构造方法常用的有5种.分别是: *数字分析法 *平方取中法 *分段叠加 *伪随机数 *除留取余法 *这里面除留取余法比较常用 *避免哈希冲突常用的方法有4种: *开放定址法(线性探测再散列.二次探测再散列) *链地址法 *再哈希法 *建立公共溢出区 其中,线性探测再散列比较常用*/ 这是一道2009年武汉科技大学的考研题,但是按照要求却做不出来,因为对7取模最多只有7个空间,不可能放进8个数,所以怀疑这道题是不是出错了,但这是考研题,应该不会出错吧.所以各位大神,你们怎

MIT算法导论——第七讲.哈希表

从作用上来讲,构建哈希表的目的是把搜索的时间复杂度降低到O(1),考虑到一个长度为n的序列,如果依次去比较进行搜索的话,时间复杂度是θ(n),或者对其先进行排序然后再搜索会更快一些,但这两种方法都不是最快的方法. 哈希表也叫散列表,他通过一个哈希函数H,把要存储的内容取一个键值,经过H的运算,把键值映射到一个有m个槽的表中去,最简单的例子就是手机里存储别人的电话号码,键值就是名字,内容就是电话号码等个人信息.这样的表有一个最大的好处就是一旦要查找某个值,比如说"张三"的电话号码,我们把

解析哈希表

网上看了很多有关的文章,感觉讲得都不够明了(原谅没读过书的我,这些基础知识都是看博客自学的).所以今天决定来讲讲哈希表 哈希表又称散列表,C#里最经典的就是Hashtable和Dictionary.特别是后面的Dictionary,大家都用得非常多.他们是以键值对的形式存储的,通过key就可以查到value,而且查询速度非常快.它内部是如何实现的呢?查询快又是为什么呢?它又有什么缺点吗?下面就来一一说明 首先,我们要开辟一个容器(数组)来存储要插入的元素,既然知道字典是以键值对的形式来存储,那我

哈希表小结

对hash table 早有耳闻,今天稍微整理总结一下. 何谓 hash table hash table的中文名称为哈希表,又叫散列表.哈希实现了一种映射,将键值key通过某种计算映射为Hash(key)值.可以这样说,散列表是用hash映射定义的一种数据结构. 将大范围的数据,映射到一个较小的范围,是不是很爽,可以节省空间.这种角度的hash,更侧重于查找. 另外,如果一个映射,可以从输入可以很容易地计算得到输出,但是根据输出结果却很难推导出其输入,这是不是很安全的一种映射(单向函数).这种

数据结构 哈希表 c++

什么是哈希表 理想的查找是不经过任何的比较,一次存取就能得到想要查询的记录:要达到这样的目的就需要在记录的储存位置和它的关键字之间建立一个确定的关系f , 让每个关键字和结构中的一个唯一的地址相对应.在查找的时候,只需要对应关系f找到给定值K的像f(K),若结构中存在关键字和K相等,则必定在f(K)的储存位置上,由此不需要任何比较就能得到查询: 就好像数组一样,我们要找第一个数,调用a[0]就能得到第一个数, 当我们通过关键字来找的时候,通过一定的规则,把关键字和储存位置建立一个映射,就能通过数

【搜索引擎(二)】索引、倒排索引、哈希表、跳表

索引 其实在计算机中我们早已接触过跟索引有关的东西,比如数据库里的索引(index),还有硬盘文件系统中其实也有类似的东西,简而言之,索引是一种为了方便找到自己需要的东西而设计出来的条目,你可以通过找索引找到自己想要内容的位置.索引过程是: 关键字->索引->文档.在图书馆内的书分门别类,就是一种按类别来分的索引.当然索引还有很多其他的实现. 仅仅有索引的概念是不够的.虽然分门别类是一种方法,但是我们在拥有一堆文档的时候必须要有从文档到索引的规范过程,并且索引的结构要满足能够让人(或者计算机)