Пользовательский связанный список, содержащий нежелательные элементы
-
22-12-2019 - |
Вопрос
Я создал собственный связанный список и классы узлов для школы и решил попрактиковаться в его использовании, создав игру, похожую на перекручивание текста.
В моем классе связанного списка у меня есть метод перемещения, который выводит слово и его длину в консоль.
Код, который у меня есть до сих пор, таков:
МойLinkedList.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());
}
}
}
МойNode.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()
вызывается, я получаю этот вывод (только конечная часть)
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
Я не могу понять, почему это происходит, но похоже, что после этого все распечатывается. abe
и он печатает abe
дважды: один раз длина регистрировалась как 3 буквы, а другой раз - как 8 букв!
Я взял текстовый файл с этого сайта:
Решение
Ваша проблема здесь в основном связана с дизайном.Главный недостаток:пытаюсь использовать один экземпляр MyNode
в нескольких связанных списках.
Когда ты InsertToHead(node)
вы изменяете содержимое node
сам, конкретно глава и последующие ссылки.
Исправить:Просто объявить new MyNode
для каждого LinkedList, в котором вы хотите его использовать.В вашем проекте вы используете два для любого узла. ll
и один из <inset_number>Letters
списки.Итак, объявите новый 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);
...
Это должно решить вашу проблему.
Если вы хотите знать, ПОЧЕМУ это произошло.Отследите код.Это связано с попыткой добавить в список узлы, к которым уже подключено еще несколько узлов.
Дополнительные замечания:
Старайтесь изо всех сил избегать
public
поля, если вы не УВЕРЕНЫ, что они вам нужны.И.Е.вMyLinkedList
кто-то, использующий ваш класс, не должен иметь доступа (или даже видеть!)counter
,head
илиtail
, поэтому их следует сделатьprivate
.Если вы действительно хотите получить к ним доступ, создайтеget
иset
методыВаш вложенный блок if
WordSort
это идеальное место для выключатель так: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 отлично работает как отдельный класс.Однако я часто буду реализовывать простой класс, например узел, в качестве вложенный класс.Это может привести к созданию очень чистого кода.Попробуйте!
Будьте осторожны при разработке классов.В вашем дизайне много дополнительных методов.Может быть легко двигаться вперед, создавая методы, которые вы можете или не можете когда-либо использовать.Мне нравится создавать методы только тогда, когда я вижу, что они мне нужны в классе, который использует рассматриваемый класс.
Приятного кодирования!