`

链地址法处理Hash冲突

阅读更多
   哈希表中的每个位置称为桶(bucket),当发生哈希冲突时就以链表形式存放多个元素。


链地址法处理Hash冲突,看看下面代码,模拟了JDK中的HashSet:
Java代码  收藏代码
  1. class  Node{ //节点数据结构    
  2.     private  Object value; //节点的值    
  3.     private  Node next; //链表中指向下一结点的引用    
  4.   
  5.     /*提供了常见的操作*/    
  6.     public  Node(Object value){ this .value = value;};   
  7.     public  Object getValue() { return  value;}   
  8.     public  Node getNext() { return  next;}   
  9.     public   void  setNext(Node next){ this .next=next;}   
  10. }   
  11.   
  12. public   class  MyHashSet { //Hash数据结构    
  13.     private  Node[] array; //存储数据链表的数组    
  14.     private   int  size =  0 ; //表示集合中存放的对象的数目    
  15.     public  MyHashSet( int  length){   
  16.         array = new  Node[length]; //创建数组    
  17.     }   
  18.   
  19.     public   int  size(){  
  20.      return  size;  
  21.     }  
  22.    
  23.     private   static   int  hash (Object o){     //根据对象的哈希码得到一个优化的哈希码,    
  24.                                         //算法参照java.util.HashMap的hash()方法    
  25.         int  h = o.hashCode();   
  26.         h += ~(h<<9 );   
  27.         h ^= (h>>>14 );   
  28.         h += (h<<4 );   
  29.         h ^= (h>>>10 );   
  30.         return  h;   
  31.     }  
  32.    
  33.     private   int  indexFor( int  hashCode){     //根据Hash码得到其索引位置    
  34.                                         //算法参照java.util.HashMap的indexFor()方法    
  35.         return  hashCode & (array.length- 1 );   
  36.     }   
  37.   
  38.     public   void  add(Object value) { //把对象加入集合,不允许加入重复的元素    
  39.         int  index = indexFor(hash(value)); //先根据value得到index    
  40.         System.out.println("index:"  + index +  " value:"  + value);   
  41.         Node newNode = new  Node(value); //由value创建一个新节点newNode    
  42.         Node node = array[index];//由index得到一个节点node    
  43.   
  44.         if  (node ==  null ) { //若这个由index得到的节点是空,则将新节点放入其中    
  45.             array[index]=newNode;   
  46.             size++;   
  47.         } else  {  
  48. //若不为空则遍历这个点上的链表(下一个节点要等于空或者该节点不等于新节点的值--不允许重复)    
  49.         Node nextNode;   
  50.        while  (!node.getValue().equals(value) && (nextNode = node.getNext())!= null ) {   
  51.                 node = nextNode;   
  52.             }   
  53.             if  (!node.getValue().equals(value)) {  
  54.              //若值不相等则加入新节点    
  55.                 node.setNext(newNode);   
  56.                 size++;   
  57.             }   
  58.         }   
  59.     }   
  60.   
  61.   
  62.     public   boolean  contains(Object value){   
  63.         int  index = indexFor(hash(value));   
  64.         Node node = array[index];   
  65.         while  (node!= null  && !node.getValue().equals(value)) {   
  66.             node = node.getNext();   
  67.         }//横向查找    
  68.         if  (node!= null  && node.getValue().equals(value)) {   
  69.             return   true ;   
  70.         } else  {   
  71.             return   false ;   
  72.         }   
  73.     }   
  74.   
  75.     public   boolean  remove(Object value) {   
  76.         int  index = indexFor(hash(value));   
  77.         Node node = array[index];   
  78.         if  (node!= null  && node.getValue().equals(value)) { //若是第一个节点就是要remove的    
  79.             array[index]=node.getNext();   
  80.             size--;   
  81.             return   true ;   
  82.         }   
  83.         Node lastNode = null ;   
  84.         while  (node!= null  && !node.getValue().equals(value)) { //若不是第一个节点就横向查找    
  85.             lastNode = node;//记录上一个节点    
  86.             node = node.getNext();   
  87.         }   
  88.         if  (node!= null  && node.getValue().equals(value)) {   
  89.             lastNode.setNext(node.getNext());   
  90.             size--;   
  91.             return   true ;   
  92.         }else  {   
  93.             return   false ;   
  94.         }   
  95.     }   
  96.   
  97.     public  Object[] getAll() {   
  98.         Object [] values = new  Object[size];   
  99.         int  index =  0 ;   
  100.         for  ( int  i =  0 ; i < array.length; i++) {   
  101.             Node node = array[i];   
  102.             while  (node!= null ) {   
  103.                 values[index++]=node.getValue();   
  104.                 node = node.getNext();   
  105.             }      
  106.         }   
  107.         return  values;      
  108.     }   
  109.     public   static   void  main(String[] args) {   
  110.         MyHashSet set = new  MyHashSet( 6 );   
  111.         Object [] values = {"Tom" , "Mike" , "Mike" , "Jack" , "Mary" , "Linda" , "Rose" , "Jone" };   
  112.         for  ( int  i =  0 ; i < values.length; i++) {   
  113.             set.add(values[i]);   
  114.         }   
  115.         set.remove("Mary" );   
  116.         System.out.println("size=" +set.size());   
  117.         values = set.getAll();   
  118.         for  ( int  i =  0 ; i < values.length; i++) {   
  119.             System.out.println(values[i]);   
  120.         }   
  121.         System.out.println(set.contains("Jack" ));   
  122.         System.out.println(set.contains("Linda" ));   
  123.         System.out.println(set.contains("Jane" ));   
  124.     }   
  125. }   



结果:
index:4 value:Tom
index:1 value:Mike
index:1 value:Mike
index:5 value:Jack
index:5 value:Mary
index:0 value:Linda
index:0 value:Rose
index:0 value:Jone
size=6
Linda
Rose
Jone
Mike
Tom
Jack
true
true
false
分享到:
评论

相关推荐

    哈希表(链地址法处理冲突)swust oj#1012

    hash表一般都采用取余构造(将一个数对n取余然后根据余数来查找是否存在该数),当两个数的余数相同时仅仅凭借余数作为下标来查找就会发生错误即hash冲突,那么链地址法其实就是将余数相同的数用链表储存起来,那么...

    人名查询哈希表设计(链地址法)

    哈希函数用除留余数法构造,用线性探测再散列法或链地址法处理冲突。 测试数据 取读者周围较熟悉的30个人名。 选作内容 (1) 从教科书上介绍的集中哈希函数构造方法中选出适用者并设计几个不同的哈希函数,比较...

    Hash-lookup.zip_hash冲突

    表头插入,使用链地址法处理冲突的哈希查找算法

    姓名Hash表

    30个中国人姓名拼音,设计Hash表,平均查找长度不超过2,用除留余数法构造,用线性探测再散列,二次探测再散列和链地址法处理冲突。完成建表和查表操作。本人的课程设计作业

    C++ hash.zip

    散列,散列函数采用除留余数法,解决冲突使用链接法,每个槽的链表为带头结点的双向链表。使用这种方法的关键是选择一个合适的除数m,可以选择m是与2的整数幂不太接近的质数

    数据结构第九章 查找作业及答案(100分).docx

    表中已有15,38,61,84四个元素,如果用线性探测法处理冲突,则元素49的存储地址是( )。 A. 8 B. 3 C. 5 D. 9 7. 平衡二叉树的查找效率呈( )数量级。 A. 常数阶 B. 线性阶 C. 对数阶 D. 平方阶 8. 设输入序列为...

    数据结构哈希表实现通讯录

    //是采用链地址法,拉链法处理冲突的散列表结构 newname-&gt;next = nam[key2]-&gt;next; //利用用户名为关键字插入 nam[key2]-&gt;next=newname; return 0; } void create() //新建节点 { int i; phone=new pnode[20]...

    南理工初试试题

    (4)(3分)按以上数据, 用链地址法处理冲突(Hash函数H(key)=key % 13),画出示意图(不要写算法) 3.(3分)已知三棵树的森林如下,试把它转化为二叉树 A G N / \ / | \ / \ B C H I K O P / | \ / \ / | \...

    数据结构题

    5. 采用开放定址法处理散列表的冲突时,其平均查找长度( )。 A.低于链接法处理冲突 B. 高于链接法处理冲突 C.与链接法处理冲突相同 D.高于二分查找 6. 若需要利用形参直接访问实参时,应将形参变量说明为( )...

    数据结构考研,计算机考研必看

    冲突处理 D. 散列函数和冲突处理 2. 顺序文件采用顺序结构实现文件的存储,对大型的顺序文件的少量修改,要求重新复制整个文件,代价很高,采用( )的方法可降低所需的代价。【北京邮电大学 2000 二、8 (20/8分...

    数据结构——第9章 数据结构 anyview作业系统答案

    9.45③ 假设哈希表长为m,哈希函数为H(x),用链地址法处理冲突。试编写输入一组关键字并建造哈希表的算法。 实现下列函数: int BuildHashTab(ChainHashTab &H, int n, HKeyType es[]) /* 直接调用下列函数 */ /*...

    超实用的jQuery代码段

    7.1 如何更好地处理图片法显示问题 7.2 如何显示图片直到页面加载完成 7.3 预加载显示图片的方法 7.4 Facebook风格的图片预加载 7.5 检查图片src是否有效 7.6 上下滑动的图片 7.7 淡入淡出一幅图片,进入另一幅图片 ...

    数据结构课设

    3) 采用链地址的方法解决冲突; 4) 查找并显示给定电话号码的记录; 5、排序算法比较 任务 :利用随机函数产生10个样本(其中之一已为正序,之一为倒序),每个样本有20000随机整数,利用直接插入排序、希尔排序...

    ZendFramework中文文档

    6.2.1. 用短语法声明选项 6.2.2. 用长语法声明选项 6.3. 读取(Fetching)选项和参数 6.3.1. 操作 Getopt 异常 6.3.2. 通过名字读取 (Fetching)选项 6.3.3. 报告选项 6.3.4. 读取非选项参数 6.4. 配置 Zend...

Global site tag (gtag.js) - Google Analytics