我的链表添加方法失败了

时间:2014-09-25 22:18:07

标签: java linked-list

现在,我的链表计划需要一个有效工作的拐杖。我需要使用(0,0,null)节点启动链接列表,因为我的addToFront()方法的空头条件不起作用。任何人都可以帮我解决这个问题吗?我需要消除程序中的零以便以后更容易使用,而这个小问题已经给我带来了数小时的痛苦。我知道这是一个失去参考的问题,请帮助我!

当前输出对于add()方法是正确的,因为我已经实现了一个拐杖方法来杀死多项式的零节点,但我真的想知道我的addToFront()方法做错了什么。它是最底层的方法,我知道if(head == null)部分失败,因为如果我没有初始化列表的第一个节点并因此绕过它,我会返回一个空列表。非常感谢你的帮助!

public Polynomial add(Polynomial p)
{   
    Polynomial newPoly = new Polynomial();
    newPoly.poly = new Node(0,0,null);
    Node curr = this.poly;
    Node curr2 = p.poly;
    float co;
    int deg;

    while(curr!=null && curr2!=null)
    {
        if(curr.term.degree == curr2.term.degree)
        {
            co = curr.term.coeff + curr2.term.coeff;
            deg = curr.term.degree;
            curr=curr.next;
            curr2=curr2.next;
        }
        else if(curr.term.degree > curr2.term.degree)
        {
            co=curr.term.coeff;
            deg = curr.term.degree;
            curr=curr.next;
        }
        else
        {
            co=curr2.term.coeff;
            deg=curr2.term.degree;
            curr2=curr2.next;
        }
        if(co!=0)
        {
            addToFront(co,deg,newPoly.poly);
        }
        // addToBack(co,deg,newPoly.poly);
        // System.out.println(newPoly.poly.term.coeff);
    }
    while(curr!=null)
    {
        co=curr.term.coeff;
        deg=curr.term.degree;
        curr=curr.next;
        if(co!=0)
        {
            addToFront(co,deg,newPoly.poly);
        }
    }
    while(curr2!=null)
    {
        co=curr2.term.coeff;
        deg=curr2.term.degree;
        curr2=curr2.next;
        if(co!=0)
        {
            addToFront(co,deg,newPoly.poly);
        }
    }




    System.out.println("Addition completed");


    killFirst(newPoly);
    newPoly = reverse(newPoly);
    killFirst(newPoly);
    return newPoly;
}









/**
 * Returns the polynomial obtained by multiplying the given polynomial p
 * with this polynomial - DOES NOT change this polynomial
 * 
 * @param p Polynomial with which this polynomial is to be multiplied
 * @return A new polynomial which is the product of this polynomial and p.
 */
public Polynomial multiply(Polynomial p) 
{
    Polynomial newPoly = new Polynomial();

    newPoly.poly = new Node(0,0,null);

    Node curr = this.poly;
    Node curr2 = p.poly;
    Polynomial tempPoly = new Polynomial();

    //for(curr=this.poly;curr!=null;curr=curr.next)
    while(curr!=null)
    {
        float x1 = curr.term.coeff;
        int y1 = curr.term.degree;
        tempPoly.poly = new Node(0,0,null);

        while(curr2!=null)
        {
            float x2 = curr2.term.coeff;
            int y2 = curr2.term.degree;

            addToFront(x1*x2, y1+y2, tempPoly.poly);
            newPoly = newPoly.add(tempPoly);
            curr2=curr2.next;
        }
        curr=curr.next;
    }

    return newPoly;
}


/**
 * Evaluates this polynomial at the given value of x
 * 
 * @param x Value at which this polynomial is to be evaluated
 * @return Value of this polynomial at x
 */



public Polynomial reverse(Polynomial p)
{
    Polynomial newPoly = new Polynomial();
    newPoly.poly = new Node(p.poly.term.coeff,p.poly.term.degree,newPoly.poly);
    while(p.poly!=null)
    {
        addToFront(p.poly.term.coeff,p.poly.term.degree,newPoly.poly);
        p.poly=p.poly.next;
    }
    return newPoly;
}

public void killFirst(Polynomial p)
{
    p.poly = p.poly.next;
}



public float evaluate(float x) 
{
    Node curr = this.poly;

    int hornerCount = 1;

    float horner = x;

    float sum = 0;
    while(curr!=null)
    {
        if(curr.term.degree==0)
        {
            sum = sum + curr.term.coeff;
        }
        else if(curr.term.degree==1)
        {
            sum = sum+(curr.term.coeff*horner);
        }
        else if(curr.term.degree>hornerCount)
        {
            for(int i=0;i<curr.term.degree-hornerCount;i++)
            {
                horner = horner*x;
            }
            System.out.println("horner ="+horner);
            sum = sum+(curr.term.coeff*horner);
            hornerCount = curr.term.degree;
        }
        curr=curr.next;
        System.out.println("+ "+sum);
    }

    return sum;
}


/* (non-Javadoc)
 * @see java.lang.Object#toString()
 */
public String toString() {
    String retval;

    if (poly == null) {
        return "0";
    } else {
        retval = poly.term.toString();
        for (Node current = poly.next ;
        current != null ;
        current = current.next) {
            retval = current.term.toString() + " + " + retval;
        }
        return retval;
    }
}

private void sort(Node head)                                        // CURRENTLY BROKEN!!!!!!!!!!
{ 
    Node temp; 
    Node prev;
    Node curr = head; 
    while(curr.next != null)
    { 
    if(curr.term.degree < curr.next.term.degree) // deg is smaller or greater 
        {//swap
            temp = curr; //save first element
            curr = curr.next; //set first element to second
            temp.next = curr.next; //set next of first to third
            curr.next = temp; //set second element to the first that we saved before
        }
    prev = curr;
    curr = curr.next; //move to next element
    }
}

private void addToFront(float coeff, int deg, Node head)
{
    // System.out.println("Hello");

    if(head==null)
    {
        System.out.println("List empty, creating new node");
        head =  new Node(coeff,deg,head);
        System.out.println(head.term.coeff);
    }
    else
    {
        Node n = new Node(coeff, deg, head.next);
        // System.out.println(n.term.coeff + " and "+ n.term.degree);
        head.next =  n;
    }


}

1 个答案:

答案 0 :(得分:0)

问题是addToFront的调用者不知道方法内部head的值已更改,因为head是局部变量。调用者只能看到传递对象的属性是否发生了变化。

这是它的工作原理(在一个简化的例子中):

第1步:在函数调用之前:

     myObject                                      Object.name   Object.whatever
+---------------+---------------+---------------+---------------+---------------+
|       4       |               |               |     name      |    whatever   |
+---------------+---------------+---------------+---------------+---------------+
        1               2               3               4               5
        |                                               ^
        +-----------------------------------------------+

myObject的引用位于RAM中的地址1。该引用说:“myObject的属性位于地址4之后”。

第2步:使用非空参数进行函数调用:

    myObject          head                         Object.name   Object.whatever
+---------------+---------------+---------------+---------------+---------------+
|       4       |       4       |               |     name      |    whatever   |
+---------------+---------------+---------------+---------------+---------------+
        1               2               3               4               5
        |               |                               ^
        |               +-------------------------------+
        |                                               ^
        +-----------------------------------------------+

当您致电addToFront时,将为head的参考分配新地址,因为head是一个对象。在这种情况下,地址2被指定用于head的引用。地址2现在说:“head的属性在地址4之后”。

这就是为什么它会影响调用者,如果传递的对象的属性被更改。如果head要更改其name属性,则地址​​4将会更改。如果稍后调用myObject.name,则地址4的内容仍将设置为新值。

第3步:使用空参数进行函数调用

    myObject           head
+---------------+---------------+---------------+---------------+---------------+
|     null      |      null     |               |               |               |
+---------------+---------------+---------------+---------------+---------------+
        1               2               3               4               5

地址1对myObject的引用只是说:“没有对象,属性无处可去”。这会被复制到head

第4步:退出功能

    myObject          head                         Object.name   Object.whatever
+---------------+---------------+---------------+---------------+---------------+
|     null      |       4       |               |     name      |    whatever   |
+---------------+---------------+---------------+---------------+---------------+
        1               2               3               4               5
                        |                               ^
                        +-------------------------------+

将某些内容分配给本地对象变量时,只有本地变量的引用在RAM中更新,但原始引用不会更改。由于局部变量中的新引用未复制回原始变量,因此函数调用未按预期执行。


为了解决您的问题,我向您介绍了两个选项:

<强> 1。总是回头并将其分配到某个地方:

方法签名: public Node addToFront(...)

致电: newPoly.poly = addToFront(co,deg,newPoly.poly);

这是有效的,因为将head中的新引用返回并分配给原始引用就像将更改的引用自动复制回原始引用一样。

<强> 2。传递Polynom对象而不是Node对象

方法签名: public void addToFront(float coeff, int deg, Polynom polynom)

在方法的最开头添加此行:Node head = polynom.poly;

这可能意味着您不能再在某些地方使用此方法。检查您是否在任何时候将somePolynom.poly以外的内容传递给方法。如果是这种情况,则无法使用此方法。

这是有效的,因为现在head的内容不是局部变量(即参数),而是传递对象的属性。