Пользовательский связанный список, содержащий нежелательные элементы

StackOverflow https://stackoverflow.com//questions/21058081

  •  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 букв!

Я взял текстовый файл с этого сайта:

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

Это было полезно?

Решение

Ваша проблема здесь в основном связана с дизайном.Главный недостаток:пытаюсь использовать один экземпляр 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 отлично работает как отдельный класс.Однако я часто буду реализовывать простой класс, например узел, в качестве вложенный класс.Это может привести к созданию очень чистого кода.Попробуйте!

  • Будьте осторожны при разработке классов.В вашем дизайне много дополнительных методов.Может быть легко двигаться вперед, создавая методы, которые вы можете или не можете когда-либо использовать.Мне нравится создавать методы только тогда, когда я вижу, что они мне нужны в классе, который использует рассматриваемый класс.

Приятного кодирования!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top