简体   繁体   English

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

[英]Custom linked list having unwanted elements

I have made a custom linked list and node classes for school and I have decided to practice how to use it by making a text-twist like game 我为学校制作了一个自定义的链接列表和节点类,并且我决定通过制作类似文本扭曲的游戏来练习如何使用它

In my linked list class, I have a traverse method which prints out the word and how long the word is into the console. 在我的链表类中,我有一个遍历方法,该方法可以打印出单词以及单词进入控制台的时间。

The code I have so far is this: 到目前为止,我的代码是:

MyLinkedList.java 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 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 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");
    }
}
}

and finally, Driver.java 最后是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);
}
}

Whenever I run this code, all the linked lists ( threeLetters , fourLetters , fiveLetters , and sixLetters ) are completely fine until the very end, when threeLetters.traverse() is called, I get this output (only the end portion) 每当我运行此代码时,所有链接列表( threeLettersfourLettersfiveLetterssixLetters )都是完全正确的,直到最后,当threeLetters.traverse()时,我都会得到此输出(仅末尾部分)

act 3
ace 3
aby 3
abe 3
abducts 7
abductors   9
abductor    8
abductions  10
abduction   9
abducting   9
abducted    8
abdominal   9
abdomens    8
abdomen 7
abdication  10
abdicating  10
abdicates   9
abdicated   9
abdicate    8
abbreviations   13
abbreviation    12
abbreviating    12
abbreviates 11
abbreviated 11
abbreviate  10
abattoirs   9
abattoir    8
abatement   9
abashed 7
abasement   9
abandons    8
abandonment 11
abandoned   9
abandon 7
abalone 7
aardwolf    8
abe 8

I can't seem to find out why it's occurring, but it looks like it's printing out everything after abe and it prints abe twice, once with it registering as 3 letters and once as 8 letters long! 我似乎不知道为什么会这样,但是看起来它在abe之后打印出所有内容,并且打印abe两次,一次以3个字母注册,一次以8个字母长!

I got the text file from this website: 我从该网站获得了文本文件:

http://www.mieliestronk.com/corncob_lowercase.txt http://www.mieliestronk.com/corncob_lowercase.txt

Your problem here is mainly one of design. 这里的问题主要是设计问题之一。 The main flaw: attempting to use one instance MyNode in multiple linked lists. 主要缺陷:尝试在多个链接列表中使用一个实例MyNode

When you InsertToHead(node) you're modifying the contents of node itself, specifically the head and next references. 当您InsertToHead(node)您正在修改node本身的内容,特别是head和next引用。

Fix: Simple declare a new MyNode for each LinkedList you want to use it in. In your project specifically you're using two for any given node. 修复:简单地为要在其中使用的每个LinkedList声明一个new MyNode 。在您的项目中,您专门为任何给定节点使用两个。 ll and one of the <inset_number>Letters lists. ll<inset_number>Letters列表之一。 So declare a new MyNode for each list: 因此,为每个列表声明一个新的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);
...

That should fix your problem. 那应该解决您的问题。

If you want to know WHY it was happening. 如果您想知道为什么会这样。 Trace the code. 跟踪代码。 It has to do with attempting to add nodes that already have some more nodes attached into a list. 它与尝试将已经添加了更多节点的节点添加到列表有关。

Additional Notes: 补充笔记:

  • Try your best to avoid public fields unless you're SURE you want them. 除非您确定要使用public场所,否则请尽量避免使用public场所。 IE in MyLinkedList someone using your class shouldn't be able to access (or even see!) the counter , head or tail , so those should be made private . MyLinkedList IE,使用您的班级的人应该无法访问(甚至看不到!) counterheadtail ,因此应将其设为private If you really want to access them, create get and set methods 如果您确实要访问它们,请创建getset方法

  • Your nested if block in WordSort is a perfect place for a switch like this: 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 works fine as a separate class. MyNode可以作为单独的类正常工作。 However I will many times choose to implement a simple class like a node as a nested class . 但是,我将很多次选择将一个简单的类(如节点)实现为嵌套类 It can make for some very clean code. 它可以编写一些非常干净的代码。 Try it out! 试试看!

  • Be careful when designing your classes. 在设计课程时要小心。 There are a lot of extra methods in your design. 您的设计中有很多额外的方法。 It can be easy to chug ahead creating methods you may or may not ever use. 提前创建您可能会或可能不会使用的方法可能很容易。 I like to only create methods when I see that I need them in a class that uses the class in question. 我只想在使用相关类的类中看到需要它们时才创建方法。

Happy Coding! 编码愉快!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM