Java 使用节点时,构造函数节点不能应用于给定类型

Java 使用节点时,构造函数节点不能应用于给定类型,java,linked-list,enqueue,Java,Linked List,Enqueue,我正在编写一个代码,如果MyStack中的新元素是唯一的,那么它会在MyStack中添加新元素。我必须复制并粘贴节点的起始代码,所以我遇到了一个问题。我一直收到两条错误消息,即使在尝试了各种解决方法之后,我也不太明白为什么。我甚至尝试过使用一些我以前使用过的助手函数,所以我特别困惑。 我经常遇到的两个错误是: -无法推断MyStack.Node的类型参数(实际参数和形式参数长度不同) -构造函数节点不能应用于给定类型。必需,无参数,找到:任何 这是我的密码: public class M

我正在编写一个代码,如果MyStack中的新元素是唯一的,那么它会在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;
     }
    }
}

公共类MyStack
{
首先是私有节点,最后是私有节点;
私有类节点
{ 
任何项目;
节点下一步;
}
公共布尔值包含(任何值)
{
for(节点curr=first;curr!=null;curr=curr.next)
{
if(值等于(当前项目)){
返回true;
}
}
返回false;
}
公共无效添加(任何值)
//方法将新值添加到列表的末尾
//完整的
{      
节点温度=第一;
while(temp.next!=null){//查找结束
温度=下一个温度;
}
temp.next=新节点(值,null);//分配新值
}
公共无效排队(任何信息){
if(this.contains(info)==true){//如果信息已经存在
System.out.println(“堆栈已包含此值”);
返回;
}
//如果我们真的需要添加信息
if(first==null){//如果堆栈中没有任何内容
节点温度=第一;
第一个=新节点(信息、温度);
第一个=温度;
返回;
}
if(first!=null){//如果已经有东西了
节点温度=第一;
while(temp.next==null)
{Node newNode=新节点(info,temp);
temp.next=newNode;
}
返回;
}
}
}

正如@Andreas已经指出的,
节点需要一个构造函数

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

使用泛型

对于您的代码,您只能存储类任何对象,这严重限制了它的可重用性。改用泛型,您可以为更多目的重用此类

链接列表

我建议您使用双链接列表的范例。这样,您就不需要找到最后一个
节点
来向堆栈添加内容<代码>节点现在有一个指向其上一个和下一个元素的指针

使用
最后一个
对象

您拥有最后一个对象,但从未使用过它。要确定当前对象是否是最后一个将值与
null
进行比较的对象。这样做的效果是,存储
null
值将破坏您的列表。相反,与对象
last
相比,此对象是唯一的,并保证您位于列表的末尾。
first
last
都是不包含值的
节点,仅用于标记列表的开始/结束

添加元素

使用上述更改,方法
enqueue(T value)
中的代码变得非常简单:您只需检查
是否包含(value)
并决定是否将值添加到列表中

所有这些更改都会导致以下代码:

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");
    }
}
公共类MyStack{
首先是私有节点,最后是私有节点;
公共MyStack(){
第一个=新节点(null,null,null);
last=新节点(null,null,first);
first.next=last;
}
私有类节点{
T项;
节点下一步;
节点前向;
公共节点(T项、下一个节点、上一个节点){
this.item=项目;
this.next=next;
this.previous=先前;
}
}
公共布尔包含(T值){
for(节点curr=first.next;curr!=last;curr=curr.next){
if(值等于(当前项目)){
返回true;
}
}
返回false;
}
/**
*方法将新值添加到列表的末尾
*/
公共无效添加(T值)
{
节点secondLast=last.previous;
添加的节点=新节点(值、最后一个、第二个);
secondLast.next=已添加;
last.previous=已添加;
}
/**
*仅当堆栈尚未包含该值时才添加该值
*/
公共无效排队(T值){
if(this.contains(value)==true){//如果信息已经存在
System.out.println(“堆栈已包含此值”);
}
否则{
增加(价值);
}
}
公共静态void main(字符串[]args){
MyStack测试=新MyStack();
测试。添加(“foo”);
测试。添加(“条”);
测试。添加(“baz”);
System.out.println(测试包含(“条”));
System.out.println(test.contains(“new”));
测试排队(“baz”);
测试排队(“MyStack”);
}
}
命名

正如你们可能已经注意到的,在我的解释中,我把这个类称为列表。这是因为它满足了列表的更多特性。堆栈通常只提供方法
push
将某些内容放在堆栈顶部,以及
pop
移除并返回最顶部的对象。(可选)
peek
可以返回最顶端的对象,而无需将其从堆栈中移除

还考虑重命名方法<代码> eNeave>代码>:队列中使用队列(很明显),队列不允许添加两个相等的对象。所以这个名字是有误导性的。我将这种方法称为

addIfN