2013-01-15 67 views
1

我正在面對java中引用的概念性問題。這是我實現的一個基本LinkedList在Java中引用的概念性問題

節點:

class Node { 
    int data; 
    Node next = null; 

    public Node(int data) { 
    this.data = data; 
    } 
} 

名單:

class LinkedList { 
    Node n = null; 
    Node start = null; 
    int flag = 0; 

    void insertion(int x) { 
    if(flag==0) 
    { 
     Node newnode = new Node(x); 
     n = newnode; 
     start = newnode; 
     flag = 1; 
     return; 
    } 

    Node newnode = new Node(x); 
    n.next = newnode; 
    n = n.next; 
    } 

    void deletion() { 
    Node str = start; 
    while(str.next.next != null) 
     str = str.next; 
    str.next = null;   
    } 

    void printlist() { 
    Node str = start; 
    while(str != null) { 
     System.out.println(str.data); 
     str = str.next; 
    } 
    } 
} 

測試類:

public class Test31 { 
    public static void main(String[] args){ 
    LinkedList ll = new LinkedList(); 
    ll.insertion(5); 
    ll.insertion(15); 
    ll.insertion(25); 
    ll.insertion(35); 
    ll.insertion(45); 
    ll.insertion(55); 
    ll.deletion();ll.deletion(); 
    ll.printlist(); 
    } 
}      

上述程序工作完全正常,沒有任何問題,但如果我用這段代碼代替deletion()

void deletion() { 
    Node str = start; 
    while(str.next != null) 
    str = str.next; 
    str = null;  
} 

然後要素的缺失不會發生。我有興趣知道爲什麼會發生這種情況。使用str.next.next可以做到這一點,但是如果我使用上面給出的刪除方法,不應該只用while循環的一次迭代實現相同的效果?

+2

請在發佈之前先格式化您的代碼。像這樣閱讀是非常困難的。你可以編輯你的問題。 – jlordo

回答

3

這是因爲其中一個str.next對象仍然引用它(或可能引用start)。通過將str設置爲null,您只需將該方法中的局部變量設置爲null,但通過將str.next設置爲null,即可刪除該str對象中的引用。

簡單的例子:

Node start = new Node(); 
Node another = new Node(); 
start.next = another; 
Node toDelete = another; 

如果你這樣做:

toDelete = null; 

在這種情況下,toDelete現在nullstart.nextanother仍包含對最初分配給對象another的引用。即使你追加這個:

another = null; 

在這種情況下,仍然有一個參考左邊。 start.next仍指向another最初分配給的原始對象。

我認爲首先刪除方法實際上是不正確也一樣,它永遠不會刪除起始節點,將拋出一個NullPointerException如果你只有因爲start.next在這一個節點是null和while循環試圖去start.next.next 。我認爲這更準確:

void deletion() { 
    Node parent = null; 
    Node current = start; 
    while (current.next != null) { 
     parent = current; 
     current = current.next; 
    } 
    if (parent == null) { 
     start = null; 
     flag = 0; 
    } else { 
     parent.next = null; 
     n = parent; 
    }  
} 
+0

我仍然不確定@mbaumbach .........就str的範圍而言,如果我使用此代碼: void刪除(){ Node str = start; (start.next!= null) start = start。下一個; start = null; start = str; \t \t } 這裏我們已經使用了類實例變量start然後刪除效果不生成..... – JackSparrow

+0

我刪除了範圍的提及,因爲我認爲它只是增加了混淆,因爲這不是真正的範圍問題,這是一個參考所有權問題。我不會建議使用'start'變量,因爲您將會改變列表的起點。當你插入一個新節點時,你正在爲其他節點的下一個變量(或第一次插入的「開始」)分配一個引用。爲了真正從列表中刪除它,您需要從擁有節點中刪除該引用。 –

+0

這是完全正確的....我得到那.....但我無法理解,如果我將str.next設置爲null,那麼類變量啓動將指向str.next指向的對象在這種情況下,它不應該是gc – JackSparrow