Java 具有不需要的元素的自定义链表
我已经为学校制作了一个自定义链接列表和节点类,我决定通过制作一个文本扭曲类游戏来练习如何使用它 在我的链表类中,我有一个遍历方法,它打印出单词以及单词进入控制台的时间 到目前为止,我掌握的代码如下: MyLinkedList.javaJava 具有不需要的元素的自定义链表,java,doubly-linked-list,Java,Doubly Linked List,我已经为学校制作了一个自定义链接列表和节点类,我决定通过制作一个文本扭曲类游戏来练习如何使用它 在我的链表类中,我有一个遍历方法,它打印出单词以及单词进入控制台的时间 到目前为止,我掌握的代码如下: MyLinkedList.java package game; public class MyLinkedList { public int counter; public MyNode head; public MyNode tail; public MyLin
package game;
public class MyLinkedList {
public int counter;
public MyNode head;
public MyNode tail;
public MyLinkedList() {
counter = 0;
}
public void InsertToHead(MyNode m) {
if (counter == 0) {
head = tail = m;
} else {
m.setNext(head);
head.setPrev(m);
head = m;
}
counter++;
}
public int size() {
return counter;
}
public boolean isEmpty() {
if (counter == 0) {
return true;
} else {
return false;
}
}
public MyNode retrieveWord(String s) {
MyNode n = head;
while (n.next != null) {
if (s.equals(n.getWord())) {
return n;
} else {
n = n.next;
}
}
if (s.equals(tail.getWord())) {
return tail;
}
return null;
}
public MyNode retrieveLength(int l) {
MyNode n = head;
while (n.next != null) {
if (l == n.getLength()) {
return n;
} else {
n = n.next;
}
}
if (l == tail.getLength()) {
return tail;
}
return null;
}
public void traverse() {
MyNode n = head;
if (head != null) {
while (n.next != null) {
System.out.println(n.getWord() + "\t" + n.getLength());
n = n.next;
}
System.out.println(tail.getWord() + "\t" + n.getLength());
}
}
}
MyNode.java
package game;
public class MyNode {
public String word;
public int length;
public MyNode next, previous;
public MyNode() {
word = null;
length = 0;
next = null;
previous = null;
}
public MyNode(String w, int l) {
word = w;
length = l;
next = null;
previous = null;
}
public void setNext(MyNode n) {
next = n;
}
public void setPrev(MyNode n) {
previous = n;
}
public void toHead(MyNode n){
while(n.previous != null){
n.setPrev(n);
}
}
public void setWord(String w){
word = w;
}
public String getWord(){
return word;
}
public void setLength(int l){
length = l;
}
public int getLength(){
return length;
}
public boolean hasNext(){
return next != null;
}
}
WordSort.java
package game;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class WordSort {
Scanner wordScan;
public WordSort() {
MyLinkedList sixLetters = new MyLinkedList();
MyLinkedList fiveLetters = new MyLinkedList();
MyLinkedList fourLetters = new MyLinkedList();
MyLinkedList threeLetters = new MyLinkedList();
MyLinkedList rejects = new MyLinkedList();
try {
wordScan = new Scanner(new File("corncob_lowercase.txt"));
wordScan.useDelimiter("\r\n");
MyLinkedList ll = new MyLinkedList();
while (wordScan.hasNext()) {
String temp = wordScan.next();
MyNode node = new MyNode();
node.setWord(temp);
node.setLength(temp.length());
ll.InsertToHead(node);
if (temp.length() == 6) {
sixLetters.InsertToHead(node);
} else if (temp.length() == 5) {
fiveLetters.InsertToHead(node);
} else if (temp.length() == 4) {
fourLetters.InsertToHead(node);
} else if (temp.length() == 3) {
threeLetters.InsertToHead(node);
} else {
rejects.InsertToHead(node);
}
}
wordScan.close();
threeLetters.traverse();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("Missing File: corncob_lowercase.txt");
}
}
}
最后是Driver.java
package game;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Driver extends JPanel {
private static final long serialVersionUID = 1L;
public Driver() {
new WordSort();
}
public static void main(String[] args) {
JFrame frame = new JFrame("Hidden Word");
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new Driver());
frame.setVisible(true);
}
}
每当我运行此代码时,所有链接列表(threeLetters
,fourLetters
,fiveLetters
,以及sixLetters
)都是完全正常的,直到最后调用threeLetters.traverse()
,我得到这个输出(只有最后部分)
我似乎无法找出它发生的原因,但它似乎在打印abe
之后的所有内容,并且它打印abe
两次,一次注册为3个字母,一次注册为8个字母
我从这个网站获得了文本文件:
您这里的问题主要是设计问题。主要缺陷:试图在多个链表中使用一个实例
MyNode
当您插入头(节点)
时,您正在修改节点本身的内容,特别是头和下一个引用
修正:
只需为每个要在其中使用的LinkedList声明一个新MyNode
。在您的项目中,对于任何给定的节点,您都会使用两个ll
和一个字母列表。因此,为每个列表声明一个新的MyNode
:
...
while (wordScan.hasNext()) {
String temp = wordScan.next();
MyNode node = new MyNode();
MyNode node2 = new MyNode();
node.setWord(temp);
node2.setWord(temp);
node.setLength(temp.length());
node2.setLength(temp.length());
ll.InsertToHead(node2);
...
这会解决你的问题
如果你想知道为什么会这样。追踪代码。它与尝试添加已将多个节点附加到列表中的节点有关
补充说明:
- 尽量避免使用
公共
字段,除非您确定需要它们。也就是说,在MyLinkedList
中,使用您的类的人不应该能够访问(甚至不能看到!)计数器
、头部
或尾部
,因此这些应该被设置为私有
。如果确实要访问它们,请创建get
和set
方法
WordSort
中的嵌套if块是这样一个函数的理想位置:
switch(temp.length()) {
case 6:
sixLetters.InsertToHead(node);
break;
case 5:
fiveLetters.InsertToHead(node);
break;
case 4:
fourLetters.InsertToHead(node);
break;
case 3:
threeLetters.InsertToHead(node);
break;
default:
rejects.InsertToHead(node);
break;
}
- MyNode作为一个单独的类运行良好。然而,我会多次选择实现一个简单的类,比如一个节点。它可以生成一些非常干净的代码。试试看
- 设计类时要小心。在你的设计中有很多额外的方法。你可以很容易地创造出你可能会用到,也可能永远不会用到的方法。我只喜欢在使用相关类的类中发现需要方法时才创建方法
快乐编码 谢谢大家!!这帮了大忙!我还添加了拒绝列表,看看它是否有帮助,这对我的代码是没有必要的
switch(temp.length()) {
case 6:
sixLetters.InsertToHead(node);
break;
case 5:
fiveLetters.InsertToHead(node);
break;
case 4:
fourLetters.InsertToHead(node);
break;
case 3:
threeLetters.InsertToHead(node);
break;
default:
rejects.InsertToHead(node);
break;
}