整数到数组中的链接列表

时间:2013-04-10 17:43:10

标签: java arrays linked-list

我正在进行一项赋值,其中整数被输入到应用程序中,整数被散列,然后被放入数组中。数组中的每个位置都是我编写的链表。我的问题是我似乎无法指定整数应该在数组中的哪个位置。目前,我的输出是数组中每个位置的最后五个整数,除了位置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中的正确位置。

2 个答案:

答案 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] = LinkedListNode(36) - &gt; Node(60) - &gt; Node(108) - &gt; Node(312)
hashTable [1] = LinkedListNode(85)
等...

目前,您正在尝试将单个链接列表的概念与链接列表集合混合在一起。我们在这里看到了这种误解:

private static MyList last;
private static MyList first;

通过将firstlast声明为类变量,您基本上会创建一个信念,即整个集合中只有一个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)不再使用firstlast,只需迭代每个元素

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 + " ");
    }
  }
}