【问题标题】:How do I implement a Hashtable using a Binary Search Tree?如何使用二叉搜索树实现哈希表?
【发布时间】:2013-06-24 15:56:55
【问题描述】:

通过简单地使用以下数据结构,我能够使用数组实现 Hashtable。

LinkedList<Item<K,V>> table[]
const int MAX_SIZE = 100

即链表数组(链式散列)。

现在在各种书籍中,他们说如果我们想要有序数据,我们可以使用 BST 实现哈希表。 如何将键和值合并到 BST 中。虽然我可以像存储单个数据项一样存储两者,但是键提供了一个整数,在它已经到哈希函数之后,它就像数组的索引一样。如何在 BST 中使用密钥?我不需要任何索引?

我能想到的是,我可以使用该功能比较两个键,然后进行正常的插入,相应的删除。

编辑:

假设我从头开始拥有 BST

class Node {
        K key;
        V value;
        Node left;
        Node right;
    }


class BinarySearchTree {
            Node root;
        }


class Hashtable {

BinarySearchTree bst;

public void Hashtable() {
bst = new BinarySearchTree();
}

//hashfunction(K key)

//get(K Key)

//put(K key,V value)

//remove(K key)

}

如何使用映射到整数的键来实现

insert(V value) 

在英国夏令时。

【问题讨论】:

标签: java hashtable binary-search-tree


【解决方案1】:

已经提供了特定于 Java 的答案,但我猜您的问题更多是关于设计而不是特定于语言的实现。

不,我们不需要计算索引或使用散列函数。如果我们将键值对存储在 bst 的节点中,那么它只是通过比较键来遍历树的问题。这也为您提供了没有冲突的额外优势,因为键是唯一的。

您可以使用散列函数并对键进行散列,然后根据该值遍历树,但是如果您不小心使用散列函数,则可能会导致冲突,然后您将不得不维护某种链接。

使用key还是key的hash值取决于key的大小。如果密钥大小很大,则将其散列到较小的大小以便更快地比较是有意义的。

【讨论】:

    【解决方案2】:

    Java 中已经有 BST 的实现 - TreeMap。这是一棵自平衡的红黑树。我想实现它不会是一个太大的问题。例如:

    public class Hashtable<T, V> implements Map<T, V> {
    
        private TreeMap<T, V> bst;
    
        public Hashtable() {
            bst= new TreeMap<T, V>();
        }
    
        @Override
        public void put(T element, V value) {
            bst.put(element, value);
        }
    
        ...
    
    }
    

    既然Hashtable应该是Map接口的实现,我建议实现java.util.Map。我会通过组合而不是继承来使用 BST——所以我们可以隐藏 BST 的 API。 BST 可以是任何东西——在我的代码示例中,我使用了 Java 的 TreeMap 类。

    【讨论】:

    • 我认为问题在于如何将其作为练习来实施,而不是您在生产中会做什么。
    • 是的,我希望实现它。我知道 Java 中的 SortedMap。
    • 根据 JDK,Dictionary 类已过时。相反,我们应该在实现自定义 HashMap 的同时实现 Map 接口。
    • 谢谢@PrabhashRathore,我已经修好了。
    【解决方案3】:

    你不需要用链表来实现哈希表。 只有当发生碰撞而不是使用需要线性时间来搜索 O(n) 的链接时,您可以使用平衡的 bst 以便搜索时间减少到 O(log n)。

    【讨论】:

      【解决方案4】:

      这是一个简单的 HashMap 实现,使用 BST 作为存储桶。这个 Map 的基本实现展示了 put() 和 get() 如何从 BST 存储桶支持的 Map 中获取数据。这个 BST 实现是不平衡的。理想情况下,对于生产应用程序,此 BST 应使用红黑树算法进行平衡,以缩短寻道时间。

      与链表相比,使用平衡 BST 实现的存储桶,我们能够将 Get(key) 时间从 O(n) 缩短到 O(log n)。

      public class HashMapWithBST {
      
          private Node[] nodes;
          private static final int MAX_CAPACITY = 41;
      
          public HashMapWithBST() {
              nodes = new Node[MAX_CAPACITY];
          }
      
          /**
           * If key is a non-null object then return the hash code of key modulo hash map size as value. If key is null then return 0.
           * 
           * @param key
           * @return hash
           */
          public int getHash(String key) {
      
              if(key == null) {
                  return 0;
              }
      
              int hash = key.hashCode();
      
              hash = hash >>> 16; // Spread the higher bits
      
              hash = hash % MAX_CAPACITY;
      
              return hash;
          }
      
          /**
           * In case of collisions, put the new key-value pair in a BST based on key comparisons.
           * 
           * @param key
           * @param value
           */
          public void put(String key, String value) {
      
              int hashOfKey = getHash(key);
      
              final Node newNode = new Node(key, value);
      
              if(nodes[hashOfKey] == null) {
      
                  nodes[hashOfKey] = newNode;
              } else {
      
                  Node root = nodes[hashOfKey];
      
                  try {
                      addToBSTBucket(root, newNode);
                  } catch(Exception e ) {
                      e.printStackTrace();
                  }
              }
      
          }
      
          /**
           * If a collision happens while adding a node to Hashmap, add new node to the hashed bucket represented with a BST.
           * 
           * @param root      root of BST bucket
           * @param newNode   New Node to be added in BST bucket
           */
          private void addToBSTBucket(Node root, final Node newNode) {
      
              if(root == null) {
                  root = newNode;
                  return;
              }
      
              Node currentNode = root;
              Node parentNode = root;
      
              while(true) {
      
                  parentNode = currentNode;
      
                  if(newNode.key.compareTo(currentNode.key) == 0) {
      
                      // if key values are same then just overwrite the vale in same node as duplicate keys are not allowed in this map
                      currentNode.value = newNode.value;
                      return;
      
                  } else if(newNode.key.compareTo(currentNode.key) < 0) {
                      currentNode = currentNode.left;
      
                      if(currentNode == null) {
                          parentNode.left = newNode;
                          return;
                      }
                  } else {
      
                      currentNode = currentNode.right;
      
                      if(currentNode == null) {
                          parentNode.right = newNode;
                          return;
                      }
                  } 
              }
      
          }
      
          /**
           * Get the value for a particular key. If no key found then return null.
           * 
           * @param key
           * @return value or null
           */
          public String get(String key) {
      
              Node node = nodes[getHash(key)];
      
              if(node != null) {
                  return getValueFromBST(node, key);
              }
      
              return null;
          }
      
          private String getValueFromBST(Node root, String key) {
      
              if(key == null) {
                  return null;
              }
      
              while(root != null) {
                  if(key.equals(root.key)) {
                      return root.value;
                  } else if(key.compareTo(root.key) < 0) {
                      root = root.left;
                  } else {
                      root = root.right;
                  }
              }
      
              return null;    
          }
      
          private static class Node {
      
              private String key;
              private String value;
              private Node left;
              private Node right;
      
              public Node(String key, String value) {
                  this.key = key;
                  this.value = value;
              }
      
          }
      }
      

      完整代码在这里:https://github.com/prabhash1785/DataStructures/blob/d842d07e1fc3bf7e1caed72eb6b0744a719a9bc6/src/com/prabhash/java/algorithms/datastructures/HashMapWithBST.java

      【讨论】:

      • 传播高位的目的是什么? hash = hash &gt;&gt;&gt; 16; // Spread the higher bits 这不会将任何小于约 100,000 的数字归零吗?
      猜你喜欢
      • 2017-11-23
      • 1970-01-01
      • 2014-05-24
      • 1970-01-01
      • 2010-10-25
      • 2010-12-06
      • 2020-04-20
      • 2015-07-23
      • 1970-01-01
      相关资源
      最近更新 更多