0

我正在编写一个代码,如果它们是唯一的,则将它们放在 MyStack 上。我不得不复制并粘贴节点起始代码,所以我遇到了一些问题。我不断收到两条错误消息,即使在尝试了各种解决方法之后,我也不太明白为什么。我什至尝试过使用我之前做过的一些辅助函数,所以我很困惑。我一直得到的两个错误是:

- 无法推断 MyStack.Node 的类型参数(实际参数和形式参数的长度不同) - 构造函数节点不能应用于给定类型。必需,无参数,找到:任何东西,

这是我的代码:





public class MyStack<Anything>
{
     private Node first, last;
     private class Node<Anything> 
     { 
         Anything item; 
         Node next; 
     }
     
     public boolean contains(Anything value)
    {
        for (Node curr = first; curr != null; curr = curr.next)
        {
            if (value.equals(curr.item))              {
                return true;
            }
        }
        return false;
    }
    
    public void add(Anything value)
  //method that adds a new value to the end of the list
    //COMPLETE
    {      
        
       Node temp = first;
    while(temp.next!=null){ //finds the end
        temp=temp.next;
    }
    temp.next=new Node(value, null); //assigns new value

}
    
     public void enqueue(Anything info){
        if (this.contains(info)==true) { //if the info is already present
            System.out.println("the stack already contains this value");
            return;
        }
        //if we actually need to add the info
         if (first == null) { //if there is nothing in the stack
        Node temp= first; 
        first = new Node<>(info,temp); 
        first = temp;
        return;
    }
      
        if (first != null) { //if there is already stuff
            Node temp = first;
        while (temp.next == null)
        {   Node newNode= new Node<>(info, temp);
            temp.next = newNode;
}
        return;
     }
    }
}
4

1 回答 1

1

正如@Andreas 已经指出的那样,Node需要一个构造函数。

您的代码中还有一些其他缺陷:

使用泛型

使用您的代码,您只能存储类的对象Anything,这极大地限制了它的可重用性。改用泛型,您可以将此类重用于更多目的。

链表

我建议,您使用双链表的范例。这样你就不需要找到最后一个Node来添加一些东西到堆栈中。Node现在有一个指向其上一个和下一个元素的指针。

使用last对象

您拥有该对象last,但从不使用它。要找出当前对象是否是您将值与 进行比较的最后一个对象null。这样做的效果是,存储一个null值会破坏你的列表。相反,与 Object 相比last,此对象是唯一的,并保证您位于列表的末尾。两者firstlast都是Node不包含值的,仅用于标记列表的开始/结束。

添加元素

使用上面的更改,Method 中的代码enqueue(T value)变得非常简单:您只需检查contains(value)并决定是否将值添加到 List 中。

应用的所有这些更改导致以下代码:

public class MyStack<T extends Object> {
    private Node first, last;
    
    public MyStack() {
        first = new Node(null, null, null);
        last = new Node(null, null, first);
        first.next = last;
    }

    private class Node {
        T item;
        Node next;
        Node previous;
        
        public Node(T item, Node next, Node previous) {
            this.item = item;
            this.next = next;
            this.previous = previous;
        }
    }

    public boolean contains(T value) {
        for (Node curr = first.next; curr != last; curr = curr.next) {
            if (value.equals(curr.item)) {
                return true;
            }
        }
        return false;
    }

    /**
     * method that adds a new value to the end of the list
     */
    public void add(T value)
    {
        Node secondLast = last.previous;
        Node added = new Node(value, last, secondLast);
        secondLast.next = added;
        last.previous = added;
    }

    /**
     * only adds value if it is not already contained by the Stack
     */
    public void enqueue(T value) {
        if (this.contains(value) == true) { // if the info is already present
            System.out.println("the stack already contains this value");
        }
        else {
            add(value);
        }
    }
    
    public static void main(String[] args) {
        MyStack<String> test = new MyStack<>();
        test.add("foo");
        test.add("bar");
        test.add("baz");
        
        System.out.println(test.contains("bar"));
        System.out.println(test.contains("new"));
        
        test.enqueue("baz");
        test.enqueue("MyStack");
    }
}

命名

您可能已经注意到,在我的解释中,我称这个类为 List。这是因为它满足了 List 的更多特性。堆栈通常只提供push将某些东西放在堆栈顶部以及pop删除和返回最顶部对象的方法。可以选择peek返回最顶层的对象,而不将其从堆栈中删除。

还要考虑重命名方法enqueue:队列(显然)中使用了入队,并且队列不禁止添加两个相等的对象。所以这个名字有误导性。我会将此方法称为addIfNotContaining.

在我看来,您应该将此类命名为 List 并添加一个方法get(int i)来获取某个位置的特定元素。自然会添加一些其他方法,例如等size。符合标准清单。但我假设你已经有了,但没有发布它们,因为它们与你的问题无关。

多线程

这个类远非线程保存。但是如果需要,我让你自己弄清楚如何让它线程保存。

于 2020-10-29T21:22:01.060 回答