Java 具有不需要的元素的自定义链表

Java 具有不需要的元素的自定义链表,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

我已经为学校制作了一个自定义链接列表和节点类,我决定通过制作一个文本扭曲类游戏来练习如何使用它

在我的链表类中,我有一个遍历方法,它打印出单词以及单词进入控制台的时间

到目前为止,我掌握的代码如下:

MyLinkedList.java

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;              
    }