哈希表的分离链接法

原理

Hash Table可以看作是一种特殊的数组。他的原理基本上跟数组相同,给他一个数据,经过自己设置的哈希函数变换得到一个位置,并在这个位置当中放置该数据。哦对了,他还有个名字叫散列

0 1
数据1 数据2

就像这个数组,0号位置放着数据1,1号位置放数据2
而我们的哈希表则是通过一个函数f(x) 把数据1变成0,把数据2变成1,然后在得到位置插入数据1和数据2。
非常重要的是哈希表的长度为素数最好!!
而且当插入数据大于一半的时候我们要进行扩充!!!

冲突问题产生

现在这个表就是2个数据,所以不会产生什么冲突,但是若一个数据他通过f(x)计算得到的位置也是0呢?是不是就跟数据1产生了冲突,因为数据1已经占据了这个位置,你无法进行插入操作。对不对。

所以我们该如何解决这个问题呢,诶,我们肯定是想两个都可以插入是不是,就像一个炸串一样把他串起来。如图
a b c就像一个炸串,而如何实现这个炸串就有多种方式。这里我们用线性表来实现

线性表实现

我们可以用java自带的List ArrayList等表,这边也给出单链表的实现方式。

public class MyArray<AnyType> {

我们首先得创建一个内部类用来存放数据,以及保存下个节点

 class ArrayNode<AnyType>{public AnyType data;public ArrayNode<AnyType> next;public ArrayNode(AnyType data){this(data,null);}private ArrayNode(AnyType data,ArrayNode<AnyType> next){this.data=data;this.next=next;}}//save type node;

设置我们这个线性表所需要的对象,例如size和一个头节点,以及我们要进行初始化,判断这个表是否为空等。

 private int theSize;//array list sizeprivate ArrayNode<AnyType> head; //head node every data behind it//init MyArraypublic MyArray(){doClear();}public void clear(){doClear();}private void doClear(){theSize=0;head=new ArrayNode<>(null);}//get size and is emptypublic int size(){return theSize;}public boolean isEmpty(){return theSize==0;}

接下来我们需要实现他的基本操作,是否包含,插入,获得以及删除。

   //containpublic boolean contains(AnyType x){ArrayNode<AnyType> newNode=head;//get a new node=headwhile (newNode.next!=null) {newNode=newNode.next;if (newNode.data == x)return true;}return false;}//get the data in idx from arraypublic AnyType get(int idx){return get(idx,head).data;}private ArrayNode<AnyType> get(int idx,ArrayNode<AnyType> node){if(idx<0||idx>size())throw new IndexOutOfBoundsException();//out of lengthArrayNode<AnyType> newNode=node;//find start head.nextfor (int i = 0; i < idx; i++)newNode=newNode.next;return newNode;}//set data into arraypublic void set(AnyType x){set(x,head);}private void set(AnyType x,ArrayNode<AnyType> node){ArrayNode<AnyType> newNode=node;while (newNode.next!=null)newNode=newNode.next;theSize++;newNode.next=new ArrayNode<>(x);}//removepublic void remove(AnyType x){remove(x,head);}private void remove(AnyType x,ArrayNode<AnyType> node){if(!contains(x))return;while (node.next!=null){node=node.next;if (node.next.data==x)break;}ArrayNode<AnyType> oldNode=node.next;node.next=null;node.next=oldNode.next;}
}

哈希表实现

public class MyHashTable<AnyType>{//define the things that we need to useprivate static final int DEFAULT_SIZE = 10;private MyArray<AnyType>[] arrays;private int currentSize;

因为我实现的是学号的存储
也就是带0开头的数据 所以我用字符串
这里这个myHash就是我实现的简单哈希函数,即获得的数据字符串化,得到最后两个字符

    private int myHash(AnyType x){String s=x.toString();return Integer.parseInt(s.substring(s.length()-2,s.length()));}

初始化哈希表,设置的默认大小为10,然后进行素数判断,如果它不是素数,那么就找到他的下一个素数作为表的大小。

    //init we should ensure that the table size is primepublic MyHashTable(){ensureTable(nextPrime(DEFAULT_SIZE));makeEmpty();}private void ensureTable(int x){arrays=new MyArray[x];for (int i = 0; i < arrays.length; i++)arrays[i]=new MyArray<>();}//make the array emptypublic void makeEmpty(){currentSize=0;for(MyArray<AnyType> myArray:arrays)myArray.clear();}//size and emptypublic int size(){return currentSize;}public boolean isEmpty(){return currentSize==0;}

基本方法的实现,插入,获得,删除,包含

    //contain xpublic boolean contains(AnyType x){int position=myHash(x);return arrays[position].contains(x);}//insert xpublic void insert(AnyType x){int position=myHash(x);if(arrays[position].contains(x))return;else if(arrays[position].size()==0)if(++currentSize>arrays.length)makeBigger();arrays[position].set(x);}//get idx datapublic MyArray<AnyType> get(int idx){ return arrays[idx];}

在这里,如果插入的时候啦,实际的currentSize大于二分之一表的大小了
则进行扩充表
一般扩充表的话,我们是直接两倍两倍扩充的。

    //makeBiggerpublic void makeBigger() {MyArray[] oldArray = arrays;arrays = new MyArray[2 * arrays.length];for (int i = 0; i < oldArray.length; i++)arrays[i] = oldArray[i];}

下一个素数查找,如果他是偶数,则给他加1这样可以大大减少开销。
然后进行下一个素数判断,奇数当中找素数。

    //nextPrimeprivate int nextPrime(int i){if(i%2==0)i++;for (; !isPrime(i); i+=2);//ensure i is jishureturn i;}

是否为素数判断,如果为2则范围true
如果是1或者为偶数则返回false
都不满足则从三开始,他的平方小于输入的数,用奇数进行操作,因为用偶数的话,前面那个2就直接判断了,所以我们用奇数,大大减少开销。
我们也可以设置他的判断条件是小于输入的二分之一,但是我们用平方进行判断大大减少了开销,而且对于奇数来说是十分有效果的。

    //is Primeprivate boolean isPrime(int i){if(i==2||i==3)return true;if(i==1||i%2==0)return false;for (int j = 3; j*j<=i ; j+=2)if (i%j==0)return false;return true;}
}

测试

public class test {public static void main(String[] args) {MyHashTable<String> a=new MyHashTable<>();a.insert("001");a.insert("01");for(int i=1;i<a.get(1).size()+1;i++){System.out.println(a.get(1).get(i));}}
}

结果

数据结构之哈希表的分离链接法java实现相关推荐

  1. 【数据结构笔记40】哈希表冲突处理方法:开放地址法(线性探测、平方探测、双散列、再散列),分离链接法

    本次笔记内容: 11.3.1 开放定址法 11.3.2 线性探测 11.3.3 线性探测-字符串的例子 11.3.4 平方探测法 11.3.5 平方探测的实现 11.3.6 分离链接法 文章目录 冲突 ...

  2. C++八股文分享---数据结构其二---哈希表

    C++八股文分享-数据结构其二-哈希表 前言 什么是哈希表? 搜索二叉树对值的查找是通过从根节点开始,逐个节点与目标值做比较,向下查找,直至找到目标值或是到达根节点未查找到,时间复杂度为O(logn) ...

  3. 【数据结构】哈希表的概念及应用

    [数据结构]哈希表的概念及应用 前言 1.写出哈希表的基本概念 2.列出常用的哈希函数构造方法,并阐述各自的特点. 直接定址法 除留余数法 数字分析法 其他构造整数关键字的哈希函数的方法: 平方取中法 ...

  4. 「Redis数据结构」哈希表(Dict)

    「Redis数据结构」哈希表(Dict) 文章目录 「Redis数据结构」哈希表(Dict) @[toc] 一.概述 二.结构 三.哈希冲突 四.链式哈希 五.rehash 六. 渐进式 rehash ...

  5. 用c语言实现基本数据结构(哈希表)

    用c语言实现基本数据结构(哈希表) 写这个哈希表总是段错误,找了半天的bug...原来是各种小错误不断,写得很蛋疼. 我是是用数组实现的,数组的最大值定义成的宏.一共只有四个函数,分别为初始化哈希表, ...

  6. 图书馆管理系统(C、数据结构、哈希表、文件IO)

    目录 技术路线 实现效果展示 ​程序主体 1.头文件部分 2.自定义函数定义部分 3.main函数部分 注意 技术路线 数据结构.哈希表.文件IO 通过C语言进行程序设计,有用到数据结构中的哈希表,通 ...

  7. Python与数据结构[4] - 散列表[1] - 分离链接法的 Python 实现

    分离链接法 / Separate Chain Hashing 前面完成了一个基本散列表的实现,但是还存在一个问题,当散列表插入元素冲突时,散列表将返回异常,这一问题的解决方式之一为使用链表进行元素的存 ...

  8. 6-23 分离链接法的删除操作函数 (20 分)

    试实现分离链接法的删除操作函数. 函数接口定义: bool Delete( HashTable H, ElementType Key ); 其中HashTable是分离链接散列表,定义如下: type ...

  9. 分离链接法的删除操作函数

    习题5.11 分离链接法的删除操作函数 (20 分) 试实现分离链接法的删除操作函数. 函数接口定义: bool Delete( HashTable H, ElementType Key ); 其中H ...

最新文章

  1. Python 与 Excel结合
  2. Jmeter实现WebSocket协议的接口和性能测试方法
  3. EM算法和GMM(上)
  4. Hadoop 2.0.0-alpha尝鲜安装和hello world
  5. linux Swap交换分区概念
  6. 微博短视频千万级高可用、高并发架构如何设计?
  7. java地图图表动态亮点,可视化图表行动指南:地表最强解读来了
  8. Android 系统(14)---SystemServer进程启动过程
  9. shell常用的命令
  10. 独木舟上的旅行(贪心)
  11. Matlab箱线图Boxplot横坐标x轴设置
  12. OSS重磅推出OSS Select——使用SQL选取文件的内容
  13. css里禁用样式,禁用某些元素的CSS样式
  14. js 计算当前时间到下个整点时间,差多少分钟,多少秒
  15. 《WiscKey: Separating Keys from Values in SSD-conscious Storage》阅读笔记
  16. Unity Blend命令
  17. 国外变电站3d可视化技术发展_从裸眼3D技术看LED显示的发展趋势
  18. ps aux指令詳解 http://blog.csdn.net/hanner_cheung/article/details/6081440
  19. 服务器怎么增加独立显卡,dell服务器设置独立显卡(dell服务器加显卡)
  20. 【PMAC学习笔记——第0篇】初识PMAC运动控制卡以及 Microsoft Visual C++ 2019,PeWin32 PRO2环境搭建

热门文章

  1. C++句柄类(露齿的猫)
  2. ucdos做程序用的c语言吗,C语言求教
  3. flex java blazeds_Flex与java通过BlazeDS实现通信(简单Demo)
  4. laravel 几种第三方接口
  5. 将qq音乐歌曲导入网易云音乐
  6. BAT(百度、阿里、腾讯)语音合成、语音播报方案调研
  7. matlab模块化编程,DSP2812基于MATLAB模块化编程的SPWM调制实现.pdf
  8. OpenAI GPT-2 官方模型下载
  9. IT服务管理系统设计思路
  10. 从蒙娜丽莎到战争机器 — 达芬奇大师科学展