我正在进行一项赋值,其中整数被输入到应用程序中,整数被散列,然后被放入数组中。数组中的每个位置都是我编写的链表。我的问题是我似乎无法指定整数应该在数组中的哪个位置。目前,我的输出是数组中每个位置的最后五个整数,除了位置10,它是null。任何帮助将不胜感激。谢谢。
public class MyHashTab {
private static MyList last;
private static MyList first;
public MyHashTab(int initialCapacity, MyList[] anArray) {
}
public static void insert(int searchKey, MyList[] anArray) {
int hash = searchKey % anArray.length;
MyList current = new MyList(searchKey);
current.next = null;
if (anArray[hash] == null) {
current.next = null;
first = current;
last = current;
anArray[hash] = current;
} else {
last.next = current;
last = current;
}
}
public static void printHash(MyList[] anArray) {
System.out.println("The generated hash table with separate chaining is: ");
for (int i = 0; i < anArray.length; i++) {
if (anArray[i] == null) {
System.out.println("\nThe items for index[" + i + "]: ");
i++;
}
System.out.print("\nThe items for index[" + i + "]: ");
MyList temp = first;
while (temp != null) {
System.out.print(temp.iData + "\t");
temp = temp.next;
}
}
}
}
public class MyList {
int iData; // This integer is used as a key value, and as a way to see the actual node instead of it's memory address.
MyList next; // This is a pointer to a nodes right child.
public MyList(int searchKey) {
this.iData = searchKey;
}
}
我认为问题在于从第26行开始的else语句。我没有指定使用哪个链表来创建新的整数部分。有没有正确的写作方式,
anArray[hash].last.next = current;
anArray[hash].last = current;
我在if和else语句中都添加了print语句,我正在使用它们。 谢谢。
输出
The generated hash table with separate chaining is:
The items for index[0]: 366 976 312 244 655
The items for index[1]: 366 976 312 244 655
The items for index[2]: 366 976 312 244 655
The items for index[3]: 366 976 312 244 655
The items for index[4]: 366 976 312 244 655
The items for index[5]: 366 976 312 244 655
The items for index[6]: 366 976 312 244 655
The items for index[7]: 366 976 312 244 655
The items for index[8]: 366 976 312 244 655
The items for index[9]: 366 976 312 244 655
The items for index[10]:
The items for index[11]: 366 976 312 244 655
预期的输出应该是这样的。生成的具有单独链接的哈希表是:
索引[0]的项目:36 60 108 312
索引[1]的项目:85
索引[2]的项目:290 422
索引项目[3]:99 135
索引项目[4]:76 148 244 568 976
索引项目[5]:29 173 245
索引[6]的项目:366
索引[7]的项目:619 655 703
索引[8]的项目:56
索引[9]的项目:345
索引[10]的项目:
索引项目[11]:23 47
经过哈希处理后,每个整数都放在arraylist中的正确位置。
答案 0 :(得分:2)
你对LinkedList是什么以及它应该如何运作有一个微妙的误解。
public class LinkedList {
//These should NOT be static
private Node last;
private Node first;
public LinkedList(Node initialNode) {
this.last = initialNode;
this.first = initialNode;
}
public static void insert(int searchKey, LinkedList[] arr) {
int hash = searchKey % arr.length;
Node newNode = new Node(searchKey);
if (arr[hash] == null) {
arr[hash] = new LinkedList(newNode);
} else {
LinkedList list = arr[hash];
list.add(newNode);
}
}
public void add(Node node) {
//here you should add this node to the end of this linked list
this.last.addNext(node); //tell the current last node about the new last node
this.last = node; //point the last pointer of this list to the new node
}
public static void printHash(LinkedList[] arr) {
System.out.println("The generated hash table with separate chaining is: ");
for (int idx = 0; idx<arr.length; idx++) {
System.out.println("\nThe items for index[" + idx + "]: ");
if (arr[idx] != null) {
arr[idx].print();
}
}
}
public void print() {
Node node = this.first;
System.out.print(temp.iData + "\t");
while (node.hasNext()){
node = node.getNext();
System.out.print(temp.iData + "\t");
}
}
}
public class Node {
int iData;
Node next = null; // This is a pointer to a nodes right child.
public MyList(int searchKey) {
this.iData = searchKey;
}
public Node getNext() {
return this.getNext();//Note this might be null!
}
public boolean hasNext() {
if (this.next == null) { return false; }
return true;
}
public void addNext(Node node) {
this.next = node;
}
}
您可以按如下方式调用此代码:
LinkedList[] arrayOfLists = new LinkedList[12];//sets up an array of 12 linked lists
LinkedList.insert(36, arrayOfLists);
arrayOfLists.printHash();
但请注意,通常对于这类事情,insert()
方法不会是静态的。理解静态成员和方法在OOP中非常重要。对于该类的所有实例,静态成员将是相同的。大多数对象必须实例化(new SomeObject()
);实例化对象拥有自己的每个非静态成员的副本。只能在实例化对象上调用非静态函数:
LinkedList.insert(36,arrayOfLists); //调用静态方法
LinkedList list = new LinkedList(Node someNode);//Instantiating a new LinkedList object
list.print();//calling a non-static function on an instantiated object
答案 1 :(得分:2)
免责声明:我跑了一会儿。我只想把所有相关的东西放下来。如果你只对解决方案感兴趣,请向下滚动到我标题为...的位置......
从一开始,就像纳撒尼尔·福特提到的那样,我相信你对HashTable实现的工作方式存在概念上的误解。让我们从打破逻辑开始。
HashTable是一种构造,用于通过计算您正在存储的对象的唯一(或几乎唯一)哈希来存储和快速检索对象。当您计算此单向散列并使用它来存储表中的对象时,您可以在理想情况下进行O(1)查找。
在一个完美的世界中,所有输入都会唯一地散列并且永远不会发生碰撞,但我们知道这是不实际的。所以当你有多个对象时,你需要有一个集合,允许你将多个对象存储到相同的哈希值;一个LinkedList
!
现在使用12个值的set数组,您需要为每个元素提供唯一的LinkedList。如果写出来,你的预期输出将是这样的:
hashTable
[0] = LinkedList
(Node(36)
- &gt; Node(60)
- &gt; Node(108)
- &gt; Node(312)
)
hashTable
[1] = LinkedList
(Node(85)
)
等...
目前,您正在尝试将单个链接列表的概念与链接列表集合混合在一起。我们在这里看到了这种误解:
private static MyList last;
private static MyList first;
通过将first
和last
声明为类变量,您基本上会创建一个信念,即整个集合中只有一个first
和一个last
变量链接列表,每个列表各自应具有自己的第一个/最后一个指针。代码的结果是逻辑,其中插入到数组中不同位置的节点引用了与它们完全无关的位置。
所以实际上,从哪里开始修复?
清理insert
方法,逐步完成。
1)计算传入对象的哈希值
2)查找数组上的哈希值
3)如果数组位置为空,则生成新的链接列表并将值插入数组中
3b)如果数组不为null,则为列表创建一个新节点,并将现有列表的最后一个节点指向新节点
4)完成
纳撒尼尔的代码非常适合这种需求,但如果你被迫使用MyList
实现,它的行为就像这样:
int hash = searchKey % arr.length;
MyList newNode = new MyList(searchKey);
MyList arrIndex = arr[hash];
if (arrIndex == null) {
arr[hash] = newNode;
} else {
while (arrIndex.next != null) {
arrIndex = arrIndex.next;
}
arrIndex.next = newNode;
}
此外,由于两个问题,您的printHash
方法需要更新。
1)在事件arr [i]中增加i
的逻辑为空可能会导致您超出界限。在数组的最后一个索引为null的情况下,您将增加i
而不检查它。你最好做这样的检查,然后让循环为你工作:
if (anArray[i] == null) {
continue;
}
或保持代码更干净(程序流程中没有随机跳转)
for (...) {
if (anArray[i] != null) {
//Code to print that array
}
}
2)不再使用first
和last
,只需迭代每个元素
for (int i = 0; i < anArray.length; i++) {
System.out.print("\nThe items for index[" + i + "]: ");
if (anArray[i] != null) {
MyList tmp = anArray[i];
while ((tmp = tmp.next) != null) {
System.out.print(tmp.iData + " ");
}
}
}