2017-10-20 114 views
0

帖子详细
在数据结构课程的通用地图,我获得了Java源代码的“二次探测哈希表”级,并要求实现一个通用的地图(与得到方法)并将密钥/定义对存储在散列表中。我在阅读本书时理解这些内容,但发现很难用编程语言(Java)来实现。我认为问题的一部分是确切地理解问题的要求,部分是Java编程体验的不足之处。我希望能得到一些关于如何处理这类问题的建议,并填写我错过的任何Java知识。实现使用哈希表中的Java

一些问题我已经
什么是哈希表类相对于一般的地图我应该创建函数?哈希表有几种方法,包括得到插入删除翻版等...是哈希表来生成一个散列值作为地图类要使用的密钥的目的是什么?密钥和定义存储在散列表中还是将它们存储在地图中?如果哈希表已经完成了所有这些,那么制作一张地图有什么意义呢?

有人可以帮我理解如何解决这样的问题吗?什么是一些可能对我有帮助的参考,或者是专门针对这个问题,或者是对如何有效和有条理地完成这种练习的理解?

我很感激我能得到的任何帮助。我包括书中的代码以帮助说明问题。

二次探查哈希表码课本

public class QuadraticProbingHashTable<AnyType> { 

    public QuadraticProbingHashTable() { 
     this(DEFAULT_TABLE_SIZE); 
    } 

    public QuadraticProbingHashTable(int size) { 
     allocateArray(size); 
     doClear(); 
    } 

    public boolean insert(AnyType x) { 
     int currentPos = findPos(x); 
     if(isActive(currentPos)) return false; 

     array[currentPos] = new HashEntry<>(x, true); 
     theSize++; 

     if(++occupied > array.length/2) rehash(); 

     return true; 
    } 

    private void rehash() { 
     HashEntry<AnyType>[] oldArray = array; 

     allocateArray(2 * oldArray.length); 
     occupied = 0; 
     theSize = 0; 

     for(HashEntry<AnyType> entry : oldArray) 
      if(entry != null && entry.isActive) insert(entry.element); 
    } 

    private int findPos(AnyType x) { 
     int offset = 1; 
     int currentPos = myhash(x); 

     while(array[currentPos] != null && !array[currentPos].element.equals(x)) { 
      currentPos += offset; 
      offset += 2; 
      if(currentPos >= array.length) currentPos -= array.length; 
     } 

     return currentPos; 
    } 

    public boolean remove(AnyType x) { 
     int currentPos = findPos(x); 
     if(isActive(currentPos)) { 
      array[currentPos].isActive = false; 
      theSize--; 
      return true; 
     } else return false; 
    } 

    public int size() { 
     return theSize; 
    } 

    public int capacity() { 
     return array.length; 
    } 

    public boolean contains(AnyType x) { 
     int currentPos = findPos(x); 
     return isActive(currentPos); 
    } 

    public AnyType get(AnyType x) { 
     int currentPos = findPos(x); 
     if(isActive(currentPos)) return array[currentPos].element; 
     else return null; 
    } 

    private boolean isActive(int currentPos) { 
     return array[currentPos] != null && array[currentPos].isActive; 
    } 

    public void makeEmpty() { 
     doClear(); 
    } 

    private void doClear() { 
     occupied = 0; 
     for(int i = 0; i < array.length; i++) array[i] = null; 
    } 

    private int myhash(AnyType x) { 
     int hashVal = x.hashCode(); 

     hashVal %= array.length; 
     if(hashVal < 0) hashVal += array.length; 

     return hashVal; 
    } 

    private static class HashEntry<AnyType> { 
     public AnyType element; 
     public boolean isActive; 

     public HashEntry(AnyType e) { 
      this(e, true); 
     } 

     public HashEntry(AnyType e, boolean i) { 
      element = e; 
      isActive = i; 
     } 
    } 

    private static final int DEFAULT_TABLE_SIZE = 101; 

    private HashEntry<AnyType>[] array; 
    private int occupied; 
    private int theSize; 

    private void allocateArray(int arraySize) { 
     array = new HashEntry[nextPrime(arraySize)]; 
    } 

    private static int nextPrime(int n) { 
     if(n % 2 == 0) n++; 

     for(; !isPrime(n); n += 2) ; 

     return n; 
    } 

    private static boolean isPrime(int n) { 
     if(n == 2 || n == 3) return true; 

     if(n == 1 || n % 2 == 0) return false; 

     for(int i = 3; i * i <= n; i += 2) 
      if(n % i == 0) return false; 

     return true; 
    } 
} 

地图骨架课本

class Map<KeyType,ValueType> { 
    public Map() 

    public void put(KeyType key, ValueType val) 
    public ValueType get(KeyType key) 
    public boolean isEmpty() 
    public void makeEmpty() 

    private QuadraticProbingHashTable<Entry<KeyType,ValueType>> items; 

    private static class Entry<KeyType,ValueType> { 
     KeyType key; 
     ValueType value; 
    } 
} 

回答

0

一般情况下,你面对的是什么implementing给定interface问题。 Map是接口 - HashTable是实现它的一种方式,即底层数据结构。

但是,我理解你的困惑,因为你提供的HashTable的定义似乎不适合这项工作,因为它似乎没有选择使用自定义键(而是始终依赖于对象的散列码用于计算散列),也没有选项可以自定义HashEntry。正如问题所指出的那样,我会说答案是“你不能”。通常,在HashTable上实现Map可以归结为处理冲突 - 一种方法不是非常有效但通常可行,只要发现冲突(在不同密钥但相同哈希的情况下),就可以重新哈希整个表,直到碰撞不再存在。更常用的答案是有一个多层次的散列表,它基本上递归地在每个层次上存储散列表(计算不同的散列函数)。另一种方法是使用数组的哈希表 - 数组本身存储具有相同哈希的元素列表 - 如果碰撞数量过大,则重新哈希表。不幸的是,这些解决方案都不能直接用您提供的样本类来实现。没有进一步的背景,我不能再多说了,但这似乎是一个设计得很差的练习(这个练习偶尔会对有类似事情的学生施加酷刑)。

在您的框架中黑客攻击的一种方法是创建一个Pair类型,其hashCode函数仅计算key.hashCode()。这样,作为一个值你可以存储一个数组(然后使用上面提到的数组方法),或者你可以存储一个元素(然后使用rehash方法)。在这两种解决方案,解决冲突处理是最困难的元素(你必须处理情况下HashTablePair,但对的value部分不equals()要插入的元素。