学习笔记:散列

一、简述

散列是一种数据访问技术,所有的数据项均有散列码与之关联。

散列码可在任何时候通过散列函数计算得到,通常为数据索引。

二、散列构造

①直接定址法:取关键字本身或其线性函数计算结果作为散列码。

②数字分析法:取关键字中分布较均匀的若干位作为散列码。

③折叠法:根据表长取关键字拆分为若干等长部分后叠加求和并去掉进位的结果作为散列码。(可存在一个不等长部分)

④平方取中法:根据表长取关键字平方数值中间的若干位作为散列码。

⑤除留余数法:根据表长取关键字模运算结果作为散列码。

三、冲突处理

①开放定址法:冲突发生后从冲突为止进行线性检索,直到检索到空的位置插入或搜索项。

②再散列法:冲突发生后使用不同的散列函数生成散列码,直到没有冲突为止。

③链地址法:每个散列码对应一个链表,直接对相应的链表进行查改即可。

④公共溢出区法:将散列表分为基本表和溢出表,将所有发生冲突的数据存入溢出表。

四、实现

①开放定址法

public class HashSet {
    private static final int MAX = 1000;
    private int[] data;

    private int modulo(int val) {
        return val % MAX;
    }

    public HashSet() {
        data = new int[MAX];
        for (int i = 0; i < MAX; i++)
            data[i] = Integer.MIN_VALUE;
    }

    public boolean add(int val) {
        int i = modulo(val);
        while (i < data.length && data[i] != Integer.MIN_VALUE) {
            if (data[i] == val)
                return false;
            else i++;
        }
        if (i < data.length) {
            data[i] = val;
            return true;
        } else return false;
    }

    public boolean remove(int val) {
        int i = modulo(val);
        while (i < data.length && data[i] != val)
            i++;
        if (i < data.length) {
            data[i] = Integer.MIN_VALUE;
            return true;
        } else return false;
    }

    public boolean contains(int val) {
        int i = modulo(val);
        while (i < data.length && data[i] != val)
            i++;
        return i < data.length;
    }
}

②链地址法

public class HashSet {
    private class Node {
        int val;
        Node next;

        Node(int x) {
            val = x;
            next = null;
        }
    }

    private static final int MAX = 10000;
    private Node[] heads;

    private int modulo(int val) {
        return val % MAX;
    }

    public HashSet() {
        heads = new Node[MAX];
        for (int i = 0; i < MAX; i++)
            heads[i] = new Node(Integer.MIN_VALUE);
    }

    public boolean add(int val) {
        int i = modulo(val);
        Node x = heads[i];
        while (x.next != null) {
            if (x.next.val == val)
                return false;
            x = x.next;
        }
        x.next = new Node(val);
        return true;
    }

    public boolean contains(int val) {
        int i = modulo(val);
        for (Node x = heads[i]; x.next != null; x = x.next)
            if (x.next.val == val)
                return true;
        return false;
    }

    public boolean remove(int val) {
        int i = modulo(val);
        for (Node x = heads[i]; x.next != null; x = x.next)
            if (x.next.val == val) {
                x.next = x.next.next;
                return true;
            }
        return false;
    }
}

原文地址:https://www.cnblogs.com/arseneyao/p/8377017.html

时间: 2024-10-31 11:31:16

学习笔记:散列的相关文章

MySQL学习笔记——2.列类型

1.tinyint 占一个字节,取值范围为-128~127 unsigned:无符号,即无负数(0~255) 常用于boolean类型/体重等数据的体现 2.int //整型 占四个字节 zerofill:零填充,无需指定unsigned 3.decimal(m,d) //浮点型 相对于float而言,其更为精确 m,d:总位数,小数所占位数 4.char(m) //定长型 m的取值范围为0~255 对于不够m长的数据会自动添加空格,虽有浪费,但速度更快 5.varchar(m) //变长型 m

python学习笔记05-序列,元组

序列:由字符串,元组,列表组成 有两个特点:可以通过索引操作符和切片操作符 索引可以是负数,str[-1]表示取出最后一个元素 切片操作符是序列名后跟一个方括号 基本操作符:len()得出序列长度 min() 得出序列中最小的值 max()得出序列中最大的值 + 连接两个序列 *重复序列元素,后接重复次数 in 判断一个字符串是否在序列中 被判断的字符需要使用引号引起来 cmp(str1,str2)比较两个的序列值是否相同 大于返回1,小于返回-1,等于返回0 当一个标签没有引号时可以应用变量,

iOS学习笔记16-数据库SQLite

一.数据库 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等.离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式: 1. 归档:NSKeyedArchiver 2. 偏好设置:NSUserDefaults 3. plist存储:writeToFile 上述的使用可以参考iOS学习笔记15-序列化.偏好设置和归档,但上述三种方法都有一个致命的缺点,那就是都无法存储大批量的数据,有性能的问题,在这个时候就是使用数据库的时候. 数据库(Database)是按照数据结构来组

Java学习笔记(2)----散列集/线性表/队列/集合/图(Set,List,Queue,Collection,Map)

1. Java集合框架中的所有实例类都实现了Cloneable和Seriablizable接口.所以,它们的实例都是可复制和可序列化的. 2. 规则集存储的是不重复的元素.若要在集合中存储重复的元素,就需要使用线性表.线性表不仅可以存储重复的元素,而且允许用户指定存储的位置.用户可以通过下标来访问线性表中的元素. 3. Java集合支持三种类型的规则集:散列集HashSet.链式散列集LinkedHashSet和树形集TreeSet.HashSet以一个不可预知的顺序存储元素:LinkedHas

C++学习笔记 &lt;hash_map&gt; &lt;散列映射&gt;

对于大型容器而言hash_map要比map快5至10倍的元素查找速度. map对其元素类型要求有一个<,hash_map要求一个==和一个散列函数. map<string,int>  m1;   //用<比较串 map<string,int Nocase>   m2;       //用Nocase()比较串 hash_map<string,int>   hm1;        //用Hash<string>()散列,用==比较 hash_map

流畅python学习笔记:第十章:序列的修改,散列和切片

前面在介绍了类的很多内置方法,比如__add__,__eq__,这里继续介绍类的两个内置方法,这2个内置方法可以将一个类实例变成一个序列的形式.代码如下 class vector(object):     def __init__(self,components):         self._components=components         print self._components     def __len__(self):         return len(self._c

数据结构学习笔记07散列查找

1.散列表(Hash) 查找的本质: 已知对象找位置. 有序安排对象:全序.半序 直接“算出”对象位置:散列 时间复杂度几乎是常量:O(1),即查找时间与问题规模无关 散列查找法的两项基本工作: 计算位置:构造散列函数确定关键词存储位置: 解决冲突:应用某种策略解决多个关键词位置相同的问题 散列(Hashing) 的基本思想是: ①以关键字key为自变量,通过一个确定的函数 h(散列函数),计算出对应的函数值h(key),作为数据对象的存储地址. ②可能不同的关键字会映射到同一个散列地址上,即h

Dynamic CRM 2013学习笔记(二十六)Reporting Service报表 动态参数、参数多选全选、动态列、动态显示行字体颜色

上次介绍过CRM里开始报表的一些注意事项:Dynamic CRM 2013学习笔记(十五)报表入门.开发工具及注意事项,本文继续介绍报表里的一些动态效果:动态显示参数,参数是从数据库里查询出来的:参数可以多选或全选:动态地显示列,列不是固定的:根据某一字段的值来动态地显示整行字体的颜色. 下面介绍详细的方法: 一.动态参数.参数多选全选 动态参数: 首先定义一个Dataset: SELECT DISTINCT new_countryId, new_codename AS name FROM ne

散列之HashTable学习

1,什么是散列? 举个例子,在日常生活中,你将日常用品都放在固定的位置,当你下次需要该东西时,直接去该地方取它.这个过程就相当于散列查找. 若将它们随意杂乱无章地存放,当需要某件东西时,只能一个地方一个地方地逐一查找,这就相当于顺序查找. 在数据结构中,数组就相当于一张散列表,因为可以根据数组下标索引直接取得该位置上的元素. 2,什么情况下用到散列? 由于散列查找相对于其它查找而言,理论上只需要O(1)时间就可以找到某元素,因此,当查找是主要的任务时,散列就是实现词典的一种很好的选择. 3,散列