【问题标题】:pushing a data on a stack is changing all the data inside to the last pushed data将数据推送到堆栈上正在将内部的所有数据更改为最后推送的数据
【发布时间】:2018-12-14 12:46:16
【问题描述】:

基本上我必须实现一个撤消和重做方法。每次更改链接列表时,此方法都将应用于字符的双链接列表,我应该将其推送到撤消堆栈上。但是,每当我推送它时,最新发送的链接列表会将堆栈中的所有内容更改为该新链接列表。 请记住,除非我使用数组来实现堆栈,否则我不能使用数组。我已经尝试解决它 2 天了,但是我一直使用的每种方法最终都会产生相同的结果我很确定问题在于我错误地推送了链接列表,但我无法弄清楚。堆栈和链接列表都可以工作,我已经在其他程序上测试过它们

这些是我的推送和弹出方法

public void push(DoubleLinkList temp) {// simple push function
    size++;
    array[++top] = temp;
}

public DoubleLinkList pop() {
    if (size == 0) {
        return null;
    }
    size--;
    DoubleLinkList n = array[top];
    array[top] = null;// to prevent possible errors
    top--;
    return n;
}

这些是我的撤消和重做方法

public void undo() {
    DoubleLinkList temp = new DoubleLinkList();
    temp.head = head;
    temp.tail = tail;
    redo.push(temp);
    DoubleLinkList x = undo.pop();

    head = x.head;
    tail = x.tail;

}

public void UndoStack() {
    DoubleLinkList temp = new DoubleLinkList();
    temp.head = head;
    temp.tail = tail;
    undo.push(temp);
}

public void redo() {
    UndoStack();
    DoubleLinkList temp = redo.pop();
    head = temp.head;
    tail = temp.tail;
}

最后,每次我从其他函数更改某些内容以将其压入堆栈时,我都会调用此方法

public void appendsub(String S) {// simple append add after the last character
    UndoStack();
    for (int i = 0; i < S.length(); i++) {
        add(S.charAt(i));
    }
}

这是双链表代码

public class DoubleLinkList {

    Node head, tail;
    int size;
    StackUndo undo;
    StackUndo redo;

    public DoubleLinkList() {
        // empty constructor
    }

    public DoubleLinkList(String S) {
        undo = new StackUndo();// creat a undo and redo stack
        redo = new StackUndo();
        size = 0;// Initialize the size
        for (int i = 0; i < S.length(); i++) {// for loop to convert the string into a link list of characters
            add(S.charAt(i));
            size++;
        }

    }

    public void Insert(int n, String S) {// the main insert function to insert at a position n
        UndoStack();
        if (n < size) {// to clear any potential errors
            Node x;
            int count = 1;
            for (x = head; x != null && count != n; x = x.getNext()) {// Traverse to the specific index
                count++;
            }
            for (int i = S.length() - 1; i >= 0; i--) {// add characters after the specific index
                addafter(x, S.charAt(i));
            }

        } else
            appendsub(S);// if the index is greater than the size just append
    }

    public void appendsub(String S) {// simple append add after the last character
        UndoStack();
        for (int i = 0; i < S.length(); i++) {
            add(S.charAt(i));
        }
    }

    public void Erasen(int pos, int n) {// function to erase n characters starting at a specific position
        UndoStack();
        Node x;
        int count = 0;
        if (pos < size) {// if the pis is greater than the size of the link list then do nothing
            for (x = head; x != null && count != pos; x = x.getNext()) {// Traverse to the specific index
                count++;
            }
            for (int i = 0; i < n; i++) {// start removing node by node n times
                Remove(x);
                x = x.getNext();
            }
        } else
            return;// if it is larger than the size then just exit
    }

    public void trailing(int n) {// function to remover from the end n elements
        UndoStack();
        Node x;
        int count = 0;
        for (x = tail; x != null && count != n; x = x.getPrev()) {
            {// reach the last element we want to keep
                count++;
            }
            tail = x;// set the last element as the new tail
            tail.setNext(null); // remove everything after that. this port isn't necessary but is just a helpful
                                // visual aid
        }
    }

    public void leading(int n) {// a function to remove from the beginning
        UndoStack();
        Node x;
        int count = 0;
        for (x = head; x != null && count != n; x = x.getNext()) {// reach the first element we want to keep
            count++;
        }
        head = x;// set the new element as the head and remove everything before it
        head.setPrev(null);
    }

    public void replace(String S, String N) {// the main replace function to replace every occurrence of sub string S
                                             // with the substring N
        UndoStack();
        Node x;
        for (x = head; x != null; x = x.getNext()) {// traverse the link list
            if (x.getC() == S.charAt(0)) {// check if the character is equal to the first character of the string that
                                          // we want to replace
                if (checkSub(x, S)) {// send it to check if the whole string is correct
                    for (int i = 0; i < S.length(); i++) {// if it is correct then start removing the element
                        Remove(x);
                        x = x.getNext();
                    }
                    for (int i = N.length() - 1; i >= 0; i--)// replace the removed element with the new string N
                        addafter(x.getPrev(), N.charAt(i));
                }
            }
        }
    }

    public void add(char c) {// a function to add a character to the end of the link list
        Node n = new Node(c);
        if (head == null) {
            head = n;
            tail = n;
            size++;
        }
        tail.setNext(n);
        n.setPrev(tail);
        tail = n;
        size++;
    }

    public void addafter(Node x, char c) {// a function to add a character after a specifiv node
        Node n = new Node(c);
        x.getNext().setPrev(n);
        n.setNext(x.getNext());
        x.setNext(n);
        n.setPrev(x);
        size++;
    }

    public void Remove(Node x) {// function to remove a node
        if (x != null) {
            Node pre = x.getPrev();
            Node nex = x.getNext();
            pre.setNext(nex);
            nex.setPrev(pre);
        }
    }

    public boolean checkSub(Node x, String S) {// this will check if a string is equal to another starting from a
                                               // specific node in a link list of characters
        for (int i = 0; i < S.length(); i++) {
            if (S.charAt(i) != x.getC())
                return false;// if it is not equal then it will return false and end else it will return true
            x = x.getNext();
        }
        return true;
    }

    public void print() {// simple print function
        for (Node i = head; i != null; i = i.getNext()) {
            System.out.print(i.getC());
        }
        System.out.println();
    }

    public void undo() {
        DoubleLinkList temp = new DoubleLinkList();
        temp.head = head;
        temp.tail = tail;
        redo.push(temp);
        DoubleLinkList x = undo.pop();

        head = x.head;
        tail = x.tail;

    }

    public void UndoStack() {
        DoubleLinkList temp = new DoubleLinkList();
        temp.head = head;
        temp.tail = tail;
        undo.push(temp);
    }

    public void redo() {
        UndoStack();
        DoubleLinkList temp = redo.pop();
        head = temp.head;
        tail = temp.tail;
    }

}

这是堆栈代码

public class StackUndo {
    private DoubleLinkList[] array;
    private int top = -1;
    private int size = 0;

    public StackUndo() {
        this.array = new DoubleLinkList[200];
    }

    public void push(DoubleLinkList temp) {// simple push function
        size++;
        array[++top] = temp;
    }

    public DoubleLinkList pop() {
        if (size == 0) {
            return null;
        }
        size--;
        DoubleLinkList n = array[top];
        array[top] = null;// to prevent possible errors
        top--;
        return n;
    }

    public DoubleLinkList getTop() {// return the top element
        DoubleLinkList n = array[top];
        return n;
    }

    public void printstack() {// print the whole stack
        for (int i = 0; i < size; i++)
            array[i].print();
    }
}

节点代码

public class Node {

    private char C;
    private Node next;
    private Node prev;

    public Node(char c) {
        super();
        C = c;
    }

    public char getC() {
        return C;
    }

    public void setC(char c) {
        C = c;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    public Node getPrev() {
        return prev;
    }

    public void setPrev(Node prev) {
        this.prev = prev;
    }

}

测试类

import java.util.Scanner;

public class Test {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int choice = 0;
        int n1 = 0, n2 = 0;
        String s, s1, s2;
        System.out.println("Enter the string:");
        System.out.print("Your string is:");
        s = input.nextLine();
        DoubleLinkList p = new DoubleLinkList(s);
        while (choice != 9) {
            System.out.print("Actions:\r\n" + "1- Insert a substring at a given position\r\n"
                    + "2- Append a substring to the end of the string\r\n"
                    + "3- Erase n characters at a given position\r\n" + "4- Erase trailing n characters\r\n"
                    + "5- Erase leading n characters\r\n" + "6- Replace all occurrences of a substring by another\r\n"
                    + "7- Undo\r\n" + "8- Redo\r\n" + "9- Exit\n" + "Enter your choice: ");
            choice = input.nextInt();
            switch (choice) {
            case 1:
                System.out.print("Enter substring to be inserted: ");
                input.nextLine();
                s = input.nextLine();
                System.out.print("Enter inserting position: ");
                n1 = input.nextInt();
                p.Insert(n1, s);
                System.out.println("Your string is: ");
                p.print();
                break;
            case 2:
                System.out.print("Enter substring to be appended: ");
                input.nextLine();
                s = input.nextLine();
                p.appendsub(s);
                System.out.println("Your string is: ");
                p.print();

                break;
            case 3:
                System.out.println("Enter the positon you want to start erasing: ");
                n1 = input.nextInt();
                System.out.println("Enter the number of characters you want to erase: ");
                n2 = input.nextInt();
                p.Erasen(n1, n2);
                System.out.println("Your string is: ");
                p.print();

                break;
            case 4:
                System.out.println("Enter the number of characters you want to erase: ");
                n1 = input.nextInt();
                p.trailing(n1);
                System.out.println("Your string is: ");
                p.print();

                break;
            case 5:
                System.out.println("Enter the number of characters you want to erase: ");
                n1 = input.nextInt();
                p.leading(n1);
                System.out.println("Your string is: ");
                p.print();

                break;
            case 6:
                System.out.print("Enter substring to be inserted: ");
                input.nextLine();
                s1 = input.nextLine();
                System.out.print("Enter substring to be replaced: ");
                s2 = input.nextLine();
                p.replace(s2, s1);
                System.out.println("Your string is: ");
                p.print();
                break;
            case 7:
                p.undo();
                p.print();
                break;
            case 8:
                p.redo();
                p.print();
                break;
            case 9:
                System.out.println("Thank you for using our program!!!!!!!!!!!!!!!!!!1");
                break;
            default:
                System.out.println("WRONG INPUT WARNING TRY AGAIN!!");
                break;
            }

        }
    }

}

【问题讨论】:

  • 能否给我们完整的代码以便我调试它?
  • 我用我所有的代码更新了帖子。
  • 我也添加了测试类

标签: java eclipse stack


【解决方案1】:

DoubleLinkList 中,您持有head,这是字符列表的开头,tail 是列表的结尾。当您添加另一个字符串时,您保持相同的head 并移动tail。所以你最终会得到一个字符序列......

head ch ch tail1 ch ch ch tail2 ch tail3

您在撤消队列中的每个条目都将具有相同的head

当您打印字符列表时。你从head 开始,直到没有更多字符为止。

public void print() {// simple print function
    for (Node i = head; i != null; i = i.getNext()) {
        System.out.print(i.getC());
    }
    System.out.println();
}

因此,您为tail 设置的内容并不重要,因为print() 方法中没有使用它。结果是,对于具有相同 head 的每个 DoubleLinkList,您会得到相同的打印结果。

您可以在 print() 中添加对 tail 的检查

例如

public void print() {// simple print function
    for (Node i = head; i != null && i != tail; i = i.getNext()) {
        System.out.print(i.getC());
    }
    System.out.println(tail.getC());
}

或者你可以克隆你的角色列表,这样你每次都有不同的头。

如果您还没有的话,我建议您看一下单元测试框架(如 Junit)。它使调试变得容易得多。

【讨论】:

  • 感谢克隆字符列表的问题。我还修复了尾部问题。
  • 我要去看看Junit,再次感谢您的帮助
猜你喜欢
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 2018-05-10
  • 1970-01-01
  • 1970-01-01
  • 2018-12-17
  • 2014-01-16
  • 2021-05-26
相关资源
最近更新 更多