我的链接列表添加方法失败

问题描述:

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


} 
+0

会创建一个sentinel头节点来解决问题吗? – arunmoezhi 2014-09-25 22:23:48

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

这是如何工作的(在一个简化的例子):

步骤1:函数调用之前:

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

myObject参考位于在RAM ADRESS 1。该引用说:“myObject的属性在地址4以后”。

第2步:在与非空参数的函数调用:

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

当你调用addToFront,新的地址将被分配给该参考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的内容不是局部变量(即参数),而是传递对象的属性。