【问题标题】:My linked list adding method is failing我的链表添加方法失败
【发布时间】:2014-09-25 22:18:06
【问题描述】:

现在,我的链表程序需要一个拐杖才能有效地工作。我需要从 (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;
    }


}

【问题讨论】:

  • 创建哨兵头节点能解决问题吗?

标签: java linked-list


【解决方案1】:

问题是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.总是返回 head 并将其分配到某个地方:

方法签名: 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 的内容不是局部变量(即参数),而是传递对象的属性。

【讨论】:

    猜你喜欢
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多