免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1656 | 回复: 1
打印 上一主题 下一主题

自定义哈希表的性能评测 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-03-06 10:24 |只看该作者 |倒序浏览
自定义哈希表的性能评测


作为一个程序员或一个软件工程师,hash(散列)必然是熟解的。


对于百万级,甚至更多的数据的数据,我们如何实现存储并不太难,可我们要实现快速的增添查找删,显然普通的数组和链表是满足不了的。数组可以满足快速的查找,链表可以实现随意的删除,我们由此不难得到一种数据结构:数组挂链表的结构,称挂链式。


以一般的数据结构实现哈希过程,在实际中会遇到比较大的问题,我们在此选择使用挂链式,作为解决hash冲突的一种解决策略。当有不同的key在hash()后得到想的hashcode的时候,我们选择在哈希表结点上悬挂链表。而当我们的数据虽时间变化的时候,显然,冲突越来越严重,我们需要解决这个问题。在冲突达到一定程度时,我们队哈希表进行扩张,对原哈希表的数据进行rehash()。


不难想象到,rehash()是一个浪费时间与空间的过程,可这是没有办法的事,因为两全其美的事不存在,我们只能根据实际情况,取舍。


自定义哈希表的结构
class HuHash{


  private Node<Item> [] list=new Node<Item> [len];


  public boolean put(K k,V v){
     if(冲突严重){
         rehash()
     }
     int index=hash(k)%len;       
     Node<Item> node=new Node<Item>(k,v);  
     if(list[index]==null){
        
     }
     
  }


  public boolean get(K k){
  
  }

  public boolean hash(K k){
  
  }
  
  public boolean rehash(){
  
  }


}




class Node<Item>{
  private Node parent;
  private Node next;
}


class Item{
   
}




性能对比(见附件):






代码实现如下:
Java代码  
package hash实现;   
  
/**  
* 哈希的实现类  
*   
* @author lenovo  
*   
*/  
public class MyHash<K, V> {   
  
    private int len;   
    private Node[] list;   
    private int count; // 计数器   
  
    public MyHash(int len) {   
        this.len = len;   
        list = new Node[len];   
        count = 0;   
    }   
  
    /**  
     * 添加元素的方法  
     *   
     * @param key  
     *            :键  
     * @param value  
     *            :  
     * @return  
     */  
    public void put(K key, V value) {   
        if (count >= 1.25 * len) { // 冲突的严重性   
            rehash();   
        }   
        int index = hash(key) % len;   
        Item<K, V> it = new Item(key, value);   
        Node node = new Node(it);   
        if (list[index] != null) { // 判断是否为空结点   
            // 添加到链表头   
            Node temp = list[index];   
            node.setNext(temp);   
        }   
        list[index] = node;   
        count++;   
    }   
  
    public V get(K k) {   
        int index = hash(k) % len;   
        Node temp = list[index];   
        while (temp != null) { // 判断此数组索引是否为空   
            if (temp.getItem().getK().equals(k))   
                return (V) temp.getItem().getV();   
            temp = temp.getNext();   
        }   
        return null;   
    }   
  
    /**  
     * 根据键移除hash表中的数据  
     *   
     * @param k  
     * @return 若存在则返回true  
     */  
    public boolean remove(K k) {   
        if (count == 0) {   
            throw new RuntimeException("哈希表中无元素,删除操作拒绝!");   
        }   
        int index = hash(k) % len;   
        Node temp = list[index];   
        while (temp != null) { // 判断此数组索引是否为空   
            if (temp.getItem().getK().equals(k)) {   
                list[index] = temp.getNext();   
                count--;   
                return true;   
            }   
            temp = temp.getNext();   
        }   
        return false;   
    }   
  
    /**  
     * 得到哈希表中元素的个数  
     *   
     * @return  
     */  
    public int size() {   
        return count;   
    }   
  
    /**  
     * SDBM散列方法  
     *   
     * @param k  
     *            :键  
     * @return 哈希值  
     */  
    private int hash(K k) {   
        String str = (String) k;   
        int hash = 0;   
        char[] chars = str.trim().toCharArray();   
        int num = 0;   
        while (num < chars.length) {   
            hash = (int) chars[num] + (hash << 6) + (hash << 16) - hash; // 进行移位运算   
            num++;   
        }   
        return (hash & 0x7FFFFFFF); // 按位与(hash和0x7ffffff转换为二进制)   
    }   
  
    /**  
     * 再散列方法  
     */  
    private void rehash() {   
        len = len * 15; // 表长扩大的倍数   
        Node[] temp = new Node[len]; // 存放rehash后数据的数组   
        Node node;   
        int index;   
        for (int i = 0; i < list.length; i++) {   
            node = list;   
            while (node != null) {   
                index = hash((K) node.getItem().getK()) % len;   
                temp[index] = node;   
                node = node.getNext();   
            }   
        }   
        list = temp; // 复制数据   
    }   
  
}  

package hash实现;

/**
* 哈希的实现类
*
* @author lenovo
*
*/
public class MyHash<K, V> {

        private int len;
        private Node[] list;
        private int count; // 计数器

        public MyHash(int len) {
                this.len = len;
                list = new Node[len];
                count = 0;
        }

        /**
         * 添加元素的方法
         *
         * @param key
         *            :键
         * @param value
         *            :
         *
  1. @return
  2.          */
  3.         public void put(K key, V value) {
  4.                 if (count >= 1.25 * len) { // 冲突的严重性
  5.                         rehash();
  6.                 }
  7.                 int index = hash(key) % len;
  8.                 Item<K, V> it = new Item(key, value);
  9.                 Node node = new Node(it);
  10.                 if (list[index] != null) { // 判断是否为空结点
  11.                         // 添加到链表头
  12.                         Node temp = list[index];
  13.                         node.setNext(temp);
  14.                 }
  15.                 list[index] = node;
  16.                 count++;
  17.         }

  18.         public V get(K k) {
  19.                 int index = hash(k) % len;
  20.                 Node temp = list[index];
  21.                 while (temp != null) { // 判断此数组索引是否为空
  22.                         if (temp.getItem().getK().equals(k))
  23.                                 return (V) temp.getItem().getV();
  24.                         temp = temp.getNext();
  25.                 }
  26.                 return null;
  27.         }

  28.         /**
  29.          * 根据键移除hash表中的数据
  30.          *
  31.          * @param k
  32.          * @return 若存在则返回true
  33.          */
  34.         public boolean remove(K k) {
  35.                 if (count == 0) {
  36.                         throw new RuntimeException("哈希表中无元素,删除操作拒绝!");
  37.                 }
  38.                 int index = hash(k) % len;
  39.                 Node temp = list[index];
  40.                 while (temp != null) { // 判断此数组索引是否为空
  41.                         if (temp.getItem().getK().equals(k)) {
  42.                                 list[index] = temp.getNext();
  43.                                 count--;
  44.                                 return true;
  45.                         }
  46.                         temp = temp.getNext();
  47.                 }
  48.                 return false;
  49.         }

  50.         /**
复制代码
* 得到哈希表中元素的个数
         *
         * @return
         */
        public int size() {
                return count;
        }

        /**
         * SDBM散列方法
         *
         * @param k
         *            :键
         * @return 哈希值
         */
        private int hash(K k) {
                String str = (String) k;
                int hash = 0;
                char[] chars = str.trim().toCharArray();
                int num = 0;
                while (num < chars.length) {
                        hash = (int) chars[num] + (hash << 6) + (hash << 16) - hash; // 进行移位运算
                        num++;
                }
                return (hash & 0x7FFFFFFF); // 按位与(hash和0x7ffffff转换为二进制)
        }

        /**
         * 再散列方法
  1. */
  2.         private void rehash() {
  3.                 len = len * 15; // 表长扩大的倍数
  4.                 Node[] temp = new Node[len]; // 存放rehash后数据的数组
  5.                 Node node;
  6.                 int index;
  7.                 for (int i = 0; i < list.length; i++) {
  8.                         node = list[i];
  9.                         while (node != null) {
  10.                                 index = hash((K) node.getItem().getK()) % len;
  11.                                 temp[index] = node;
  12.                                 node = node.getNext();
  13.                         }
  14.                 }
  15.                 list = temp; // 复制数据
  16.         }

  17. }



  18. Java代码  
  19. package hash实现;   
  20. /**  
  21. * 链表结点类,存放键值对  
  22. * @author lenovo  
  23. *  
  24. */  
  25. public class Node {   
  26.       
  27.     private Node next;   
  28.     private Item item;   
  29.       
  30.     public Node(Item item){   
  31.         this.item=item;   
  32.         next=null;   
  33.     }   
  34.   
  35.     public Item getItem() {   
  36.         return item;   
  37.     }   
  38.   
  39.     public void setItem(Item item) {   
  40.         this.item = item;   
  41.     }   
  42.   
  43.     public Node getNext() {   
  44.         return next;   
  45.     }   
  46.   
  47.     public void setNext(Node next) {   
  48.         this.next = next;   
  49.     }   
  50.       
  51. }  

  52. package hash实现;
  53. /**
  54. * 链表结点类,存放键值对
  55. * @author lenovo
  56. *
  57. */
  58. public class Node {
  59.        
  60.         private Node next;
  61.         private Item item;
  62.        
  63.         public Node(Item item){
  64.                 this.item=item;
  65.                 next=null;
  66.         }

  67.         public Item getItem() {
  68.                 return item;
  69.         }

  70.         public void setItem(Item item) {
  71.                 this.item = item;
  72.         }

  73.         public Node getNext() {
  74.                 return next;
  75.         }

  76.         public void setNext(Node next) {
  77.                 this.next = next;
  78.         }
  79.        
  80. }
复制代码
Java代码
  1. package hash实现;   
  2. /**  
  3. * 键值对  
  4. * @author lenovo  
  5. *  
  6. */  
  7. public class Item<K,V> {   
  8.   
  9.     private K k;   
  10.     private V v;   
  11.       
  12.     public Item(K k,V v){   
  13.         this.k=k;   
  14.         this.v=v;   
  15.     }   
  16.       
  17.     public K getK() {   
  18.         return k;   
  19.     }   
  20.     public void setK(K k) {   
  21.         this.k = k;   
  22.     }   
  23.     public V getV() {   
  24.         return v;   
  25.     }   
  26.     public void setV(V v) {   
  27.         this.v = v;   
  28.     }   
  29.       
  30.       
  31. }  
复制代码

论坛徽章:
0
2 [报告]
发表于 2012-03-12 19:51 |只看该作者
谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP