发布详情
在数据结构课程中,我获得了用于"二次探测哈希表的Java源代码"类并要求实现通用映射(使用 get 和 put 方法)并将键/定义对存储在散列表中。我在阅读本书时理解这些材料,但发现很难用编程语言(Java)实现。我认为问题的一部分是确切地理解问题需要什么,部分是Java编程经验的缺陷。我希望收到一些关于我如何解决这类问题的建议,并填写我所遗漏的任何Java知识。
我有些问题
哈希表类与我应该创建的通用映射相关的功能是什么?哈希表有几种方法,包括 get , insert , remove , rehash 等等......目的是什么哈希表生成哈希值以用作地图类中的键?密钥和定义是存储在哈希表中还是存储在地图中?如果哈希表已经完成了所有这些,那么制作地图的重点是什么?
有人可以帮我理解如何处理这样的问题吗?有哪些参考文献可以帮助我,或者特别是这个问题,或者理解如何有效地和有条不紊地完成这种类型的锻炼?
我很感激能得到的任何帮助。我包括本书中的代码,以帮助说明问题。
教科书中的二次探测哈希表代码
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 :(得分:0)
通常,您所面临的问题是implementing
给定interface
的问题。 Map
是接口 - HashTable
是实现它的一种方法,即基础数据结构。
但是,我理解您的困惑,因为您提供的HashTable
的定义似乎不适合该工作,因为它似乎没有选择使用自定义键(而是始终依赖于对象的用于计算哈希值的哈希码)也没有选项来自定义HashEntry
。在指出问题时,我会说答案是&#34;你不能&#34;。通常,在Map
上实现HashTable
归结为处理冲突 - 一种方法虽然效果不大但通常有效,但每当您发现碰撞时(您有不同的密钥但是相同的哈希),你重新整理整个表,直到碰撞不再存在。更常见的答案是具有多级散列表,其基本上递归地存储每个级别上的散列表(计算不同的散列函数)。另一种方法是使用数组的哈希表 - 其中数组本身存储具有相同哈希的元素列表 - 并且如果冲突的数量太大则重新散列。遗憾的是,这些解决方案都不能直接与您提供的示例类一起实现。没有进一步的背景,我真的不能说更多,但它似乎是一个设计糟糕的练习(这来自偶尔用类似的东西折磨学生的人)。
在您的框架内对此进行黑客攻击的方法是创建Pair
类型,其hashCode
函数只计算key.hashCode()
。这样,作为一个值你可以存储一个数组(然后使用我上面提到的数组方法),或者你可以存储一个元素(然后使用rehash方法)。在任何一种解决方案中,解决碰撞处理是最困难的因素(您必须处理HashTable
contains()
Pair
value
的情况,但该对的equals()
部分不会#39; t window.globalLibrary = {
func1: function() {
console.log("Real func1");
return "func1";
},
obj: "This isn't a function",
func2: function(a, b) {
console.log("Real func2");
return a * a + b;
}
};
Object.keys(window.globalLibrary).forEach(function(prop) {
if (typeof window.globalLibrary[prop] == "function") {
var func = window.globalLibrary[prop];
window.globalLibrary[prop] = function() {
console.log("Calling: " + prop + "(" + Array.from(arguments) + ")");
return func.apply(this, arguments);
};
}
});
console.log(globalLibrary.func1());
console.log(globalLibrary.func2(10, 35));
console.log(globalLibrary.obj);
要插入的元素。