2016-11-06 63 views
0

我一直在盯着這一點的代碼,感覺像一個星期,不知道發生了什麼。我目前有一個LinkedList需要添加500個元素。在我添加元素0的第一次運行中,它工作正常。它認爲這是第一個因素,創建一個新的頭,然後繼續前進。問題是,當代碼回來添加元素1時,頭部突然被重置爲空,所以它會移動並使另一個頭部踢出前一個頭部。在第三次運行時,代碼識別出有一個頭部,並嘗試添加元素2.但是,尺寸變量n聲稱在LinkedList中有2個元素,因爲第一個頭部消失,實際上只有一個元素。因此,尋找第二個元素時會引發NullPointerException。那頭頭髮生了什麼?它通過add()方法完成,但它回來時不在那裏。但它又回來了嗎?我的鏈接列表的頭突然消失/重置爲空

這裏的一切是走錯了具體方法:

public void add(int i, value_type value) { 
    n++; 
    System.out.println(head==null); 
    if (i < 0 || i >= size()) 
     throw new IndexOutOfBoundsException(); 

    System.out.println(i); 
    ListNode<value_type> tmp; 
    if (head == null) { 
     System.out.println("0"); 
     head = new ListNode<value_type>(value, head); 
    } else { 
     System.out.println("1"); 
     tmp = head; 
     for (int k=0; k < i-1; k++) { 
      System.out.println("For Loop Reached"); 
      tmp = tmp.next; 
     } 
     if (i == 1) { 
      ListNode<value_type> u = new ListNode<value_type>(value); 
      tmp.next = u; 
     } 

     tmp.next = new ListNode<value_type>(value); 

    } 
    System.out.println(head==null); 
    System.out.println(""); 
} 

而這裏的全班同學:

/** 
* 
*/ 
package data_structures; 

import com.sun.corba.se.impl.orbutil.graph.Node; 

/** 
* @author 
* 
*/ 

/** 
* The ListNode<value_type> is a helper class for your 
* LinkedList<value_type> class. As its not intended for use 
* outside the LinkeList class, we are keeping it simple -- the 
* two properties will be access directly, instead of going through 
* inspectors and mutators. 
* 
* DO NOT MODIFY THIST CLASS. 
* 
* @param <value_type> The type of object to be stored in the list. 
*/ 
class ListNode<value_type> { 
    public value_type value; 
    public ListNode<value_type> next; 

    public ListNode(value_type v) { 
     value = v; 
     next = null; 
    } 

    public ListNode(value_type v, ListNode<value_type> n) { 
     value = v; 
     next = n; 
    } 

} 


/* 
* We will implement this as a single linked list. 
*/ 
public class LinkedList<value_type> extends Sequence<value_type> { 

    /** 
    * head will be the first node of the list -- or null if the list is empty 
    */ 
    private ListNode<value_type> head; 


    /** 
    * List constructor: must call the superclass constructor. 
    */ 
    public LinkedList() { 
     super(); 
     head = null; 
    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#get(int) 
    */ 
    @Override 
    public value_type get(int i) { 
     if (i < 0 || i >= size()) 
      throw new IndexOutOfBoundsException(); 

     ListNode<value_type> tmp = head; 
     for (int k=0; k < i; k++) { 
      tmp = tmp.next; 
     } 


     return tmp.value; 
    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#set(int, java.lang.String) 
    */ 
    @Override 
    public value_type set(int i, value_type value) { 
     if (i < 0 || i >= size()) 
      throw new IndexOutOfBoundsException(); 

     if (head == null) { 
      throw new IndexOutOfBoundsException(); 
     } 

     ListNode<value_type> tmp = head; 
     for (int k=0; k < i; k++) { 
      tmp = tmp.next; 
     } 

     if (tmp == null) { 
      throw new IndexOutOfBoundsException(); 
     } 

     return tmp.value; 
    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#add(int, java.lang.String) 
    */ 
    @Override 
    public void add(int i, value_type value) { 
     n++; 
     System.out.println(head==null); 
     if (i < 0 || i >= size()) 
      throw new IndexOutOfBoundsException(); 

     System.out.println(i); 
     ListNode<value_type> tmp; 
     if (head == null) { 
      System.out.println("0"); 
      head = new ListNode<value_type>(value, head); 
     } else { 
      System.out.println("1"); 
      tmp = head; 
      for (int k=0; k < i-1; k++) { 
       System.out.println("For Loop Reached"); 
       tmp = tmp.next; 
      } 
      if (i == 1) { 
       ListNode<value_type> u = new ListNode<value_type>(value); 
       tmp.next = u; 
      } 

      tmp.next = new ListNode<value_type>(value); 

     } 
     System.out.println(head==null); 
     System.out.println(""); 

    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#remove(int) 
    */ 
    @Override 
    public value_type remove(int i) { 
     if (i < 0 || i >= size()) 
      throw new IndexOutOfBoundsException(); 

     ListNode<value_type> tmp = head; 
     for (int k=0; k < i; k++) { 
      tmp = tmp.next; 
     } 

     ListNode<value_type> a = tmp; 
     ListNode<value_type> b = tmp.next.next; 
     a.next = b; 

     return tmp.value; 
    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#clear() 
    */ 
    @Override 
    public void clear() { 
     head = null; 
    } 



} 
+0

能否請您與您的實際代碼共享該鏈表的使用情況如何? – mtyurt

+0

你的意思是我項目中的其餘代碼? –

+0

'remove'功能對於移除頭部並不安全,而且很麻煩。這可能是問題所在。我建議你看一下示例鏈表實現。 – mtyurt

回答

0

我想通過爲i=0i=1添加特殊情況,因爲我相信Gene引用的時候。我還添加了一個尾部變量,用於添加到列表的末尾。

public void add(int i, value_type value) { 
    if (i < 0 || i > size()) 
     throw new IndexOutOfBoundsException(); 

    //if the size of the list is 0, create a new head 
    if (n==0) { 
     head = new ListNode<value_type>(value, head); 
     tail = head; 
    } else if (i==0) { //if the size isn't 0, but i is 0, add a new head 
     ListNode<value_type> u = new ListNode<value_type>(value, head); 
     head = u; 
    } else if (i==n) { //if adding onto the end, make a new tail 
     ListNode<value_type> u = new ListNode<value_type>(value); 
     tail.next = u; 
     tail = u;   
    } else { //else, traverse through the list to the appropriate spot 
     ListNode<value_type> tmp; 
     tmp = head; 
     for(int k=0; k < i-1; k++) { 
      tmp = tmp.next; 
     } 
     ListNode<value_type> u = new ListNode<value_type>(value, tmp.next); 
     tmp.next = u; 
    } 

    n++; //increase the size of the list by 1 

} 

固定類的其餘部分是如下:

/** 
* 
*/ 
package data_structures; 

import com.sun.corba.se.impl.orbutil.graph.Node; 

/** 
* The ListNode<value_type> is a helper class for your 
* LinkedList<value_type> class. As its not intended for use 
* outside the LinkeList class, we are keeping it simple -- the 
* two properties will be access directly, instead of going through 
* inspectors and mutators. 
* 
* DO NOT MODIFY THIST CLASS. 
* 
* @param <value_type> The type of object to be stored in the list. 
*/ 
class ListNode<value_type> { 
    public value_type value; 
    public ListNode<value_type> next; 

    public ListNode(value_type v) { 
     value = v; 
     next = null; 
    } 

    public ListNode(value_type v, ListNode<value_type> n) { 
     value = v; 
     next = n; 
    } 

} 


/* 
* We will implement this as a single linked list. 
*/ 
public class LinkedList<value_type> extends Sequence<value_type> { 

    /** 
    * head will be the first node of the list -- or null if the list is empty 
    */ 
    private ListNode<value_type> head, tail;      

    /** 
    * List constructor: must call the superclass constructor. 
    */ 
    public LinkedList() { 
     super(); 
     head = null; 
     tail = null; 
    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#get(int) 
    */ 
    @Override 
    public value_type get(int i) { 
     if (i < 0 || i >= size()) 
      throw new IndexOutOfBoundsException(); 


     ListNode<value_type> tmp = head; 
     if (i==0) { 
      return head.value; 
     } else { 
      for (int k=0; k < i; k++) { 
       tmp = tmp.next; 
      } 
     } 


     return tmp.value; 
    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#set(int, java.lang.String) 
    */ 
    @Override 
    public value_type set(int i, value_type value) { 
     System.out.println(n); 
     if (i < 0 || i >= size()) 
      throw new IndexOutOfBoundsException(); 

     if (i==0) { 
      value_type s = head.value; 
      head.value = value; 
      return s; 
     } else { 
      ListNode<value_type> tmp = head; 
      for (int k=0; k < i; k++) { 
       tmp = tmp.next; 
      } 
      value_type s = tmp.value; 
      tmp.value = value; 
      return s; 
     } 
    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#add(int, java.lang.String) 
    */ 
    @Override 
    public void add(int i, value_type value) { 
     if (i < 0 || i > size()) 
      throw new IndexOutOfBoundsException(); 

     if (n==0) { 
      head = new ListNode<value_type>(value, head); 
      tail = head; 
     } else if (i==0) { 
      ListNode<value_type> u = new ListNode<value_type>(value, head); 
      head = u; 
     } else if (i==n) { 
      ListNode<value_type> u = new ListNode<value_type>(value); 
      tail.next = u; 
      tail = u;   
     } else { 
      ListNode<value_type> tmp; 
      tmp = head; 
      for(int k=0; k < i-1; k++) { 
       tmp = tmp.next; 
      } 
      ListNode<value_type> u = new ListNode<value_type>(value, tmp.next); 
      tmp.next = u; 
     } 

     n++; 

    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#remove(int) 
    */ 
    @Override 
    public value_type remove(int i) { 
     if (i < 0 || i >= size()) 
      throw new IndexOutOfBoundsException(); 

     ListNode<value_type> tmp = head; 
     if (i==0) { 
      if (n==1) { 
       head.next = null; 
       n--; 
       return head.value; 
      } else { 
       value_type save = head.value; 
       head = head.next; 
       n--; 
       return save; 
      } 
     } 
     for (int k=0; k < i-1; k++) { 
      tmp = tmp.next; 
     } 

     ListNode<value_type> a = tmp; 
     value_type save = tmp.next.value; 
     ListNode<value_type> b = tmp.next.next; 
     a.next = b; 

     n--; 

     return save; 
    } 

    /* (non-Javadoc) 
    * @see data_structures.Sequence#clear() 
    */ 
    @Override 
    public void clear() { 
     head = null; 
     n = 0; 
     tail=null; 
    } 



} 
0

的代碼相當壞了。你會通過自己修復它來學習。

正確處理插入的特殊情況不是headnull。這是當你想在位置0的邏輯插入大致

if desired insert position is 0 // we're inserting at head 
    head = new node(val, head); // new head points to old rest of list (maybe null) 
else 
    tmp = head; 
    advance tmp to point to the element before the desired position. 
    tmp.next = new node(val, tmp.next); // insert at desired position 

在最後一步,你這是理想的位置點到新節點和新節點指向舊「下一個之前的節點「元素,這是完全正確的。這隻能在之前的所需位置之前的元素才起作用。當期望的位置大於0時,情況就是這樣。

在這個討論中我忽略了列表之外的所需位置。您需要爲它們添加throw邏輯。

最後,請注意,對於學習這是好的,但在真實系統中,您從來不會以這種方式構建500個元素的列表。當你插入第500個元素時,前進到所需位置需要498次循環迭代。有更有效的方法。

+0

所以當我想添加一個元素到列表的末尾時,我不能只調用'tmp.next',並將它設置爲一個新節點,因爲'tmp.next'不存在了嗎?所以我需要創建一個節點,將新節點設置爲「next」,然後將這兩個節點添加到列表的末尾?這感覺很麻煩。 –