2012-08-30 4 views
0

저는 Java에 익숙하지 않고 연결된 목록을 구현하려고합니다. (이 목적을 위해 목록 클래스가 존재한다는 것을 알고 있지만, 처음부터이 클래스를 사용하면 언어가 내부적으로 어떻게 작동하는지 이해할 수 있습니다)객체 값 null

주 방법에서는 4 개의 노드를 선언하고 3을 초기화합니다. 연결된 목록의 헤드 노드는 null로 설정됩니다. 매개 변수 head 및 newNode를 사용하여 add 함수를 처음 호출하면 head가 null이므로 머리를 초기화하고 newNode의 값을 this에 할당합니다. main 메서드에서 head 객체가 add 메서드에서 설정 한 새 값을 가져야합니다. 그러나 머리는 여전히 null입니다.

왜 그런지 이해해 주셔서 감사합니다.

코드가 깨끗하지 않으면 죄송합니다. 감사합니다.

public class LinkedList 
{ 
    public void add(Node newNode, Node head) 
    { 
     if(head == null) 
     { 
      head = new Node(); 
      head = newNode;    
     } 
     else 
     { 
      Node temp = new Node(); 
      temp = head; 

      while(temp.next!=null) 
      { 
       temp = temp.next; 
      } 
      temp.next = newNode; 
     }  
    } 

    public void traverse(Node head) 
    { 
     Node temp = new Node(); 
     temp = head; 

     System.out.println("Linked List:: "); 

     while(temp.next!=null); 
     { 
      System.out.println(" " + temp.data); 
      temp = temp.next; 
     } 
    } 

    public static void main(String args[]) 
    { 
     Node head = null; 
     Node newNode = new Node(null, 5); 
     Node newNode2 = new Node(null, 15); 
     Node newNode3 = new Node(null,30); 

     LinkedList firstList = new LinkedList(); 

     firstList.add(newNode,head); 

     // Part that I don't understand 
     // why is head still null here? 

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

     firstList.traverse(head); 
     firstList.add(newNode2,head); 
     firstList.traverse(head); 
     firstList.add(newNode3,head); 
     firstList.traverse(head); 

    } 

} 

public class Node 
{ 
    public Node next; 
    public int data; 

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

    public Node() 
    { 
     this.next = null; 
     this.data = 0; 
    } 

} 
+1

당신은 [찾을 수를 제공해야 이 게시물] (http://stackoverflow.com/questions/40480/is-java-pass-by-reference) interesting. 코드 상단에'head = new Node()'라고 쓰면 인수의 로컬 복사본을 변경하지만 호출 코드에서 값을 변경하지는 않습니다. – assylias

+0

디버깅을 위해 취한 조치는 무엇입니까? –

답변

2

Java 메소드 인수는 값으로 전달됩니다.

public void add(Node newNode, Node head) 
{ 
    if(head == null) 
    { 
     head = new Node(); 
     head = newNode;    
    } 
    ... 

상기

add의 범위에서 로컬 변수를 수정 head. 범위 변수 head에 대한 참조는 main 범위에 속하지 않습니다. 호출자가 새 값을 검색 할 수있게하려면 값을 반환해야합니다.


완전히 솔직히 말해서, 객체 지향 프로그래밍의 중요한 원칙은 캡슐화이다; LinkedListhead은 이상적으로 내부적으로 유지되는 필드 여야합니다. 왜 그것이 분리 된 부분이어야 하는가? head을 정말로 분리하려면 traverseadd이 정적이지 않은 이유는 무엇입니까? 디자인을 수정해야합니다. 코드 here을 다시 작성하기로 결정했습니다.

final class List { 

    private Node head; 

    public void add(final Node node) { 
    if (head == null) { 
     head = new Node(); 
    } 
    Node cur; 
    for (cur = head; cur.next != null; cur = cur.next) 
     ; 
    cur.next = node; 
    } 

    public String toString() { 
    final StringBuilder builder = new StringBuilder("Linked List::"); 
    for (Node cur = head.next; cur != null; cur = cur.next) { 
     builder.append("\n ").append(cur.data); 
    } 
    return builder.toString(); 
    } 
} 

final class Node { 

    int data; 
    Node next; 

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

    Node() { } 
} 

은 .. 그 다음, 시험 :

private static Node[] nodesFor(final int... values) { 
    int n = values.length; 
    final Node[] nodes = new Node[n]; 
    while (n > 0) { 
     nodes[--n] = new Node(values[n]); 
    } 
    return nodes; 
    } 

    public static void main(final String[] argv) { 
    final List list = new List(); 
    for (final Node node : nodesFor(5, 15, 30)) { 
     list.add(node); 
     System.out.println(list); 
    } 
    } 
0
firstList.add(newNode,head); 

    /* 
    Part you should know is, head is a local variable pointing to null. 
    Passing head as parameter doesn't make it feasible to alter this local variable. 
    Your check is worthless. 
    Make public Node add(Node newNode, Node head) and return head from there. 
    */ 
    head=firstList.add(newNode,head); 

    if(head==null) 
    { 
    System.out.println("true"); 
    } 
1

메이커 다른 노드가 호출 코드에 영향을 미치지 않는다 "헤드"참조 (자바는 자바에 대한 참조를 전달하는 " 값 ").

당신은 머리에 영구적 인 참조가 필요하므로 귀하의 클래스의 필드합니다

private Node head = new Node(); // the head of your Node tree 

public void add(Node newNode, Node parent) { 
    // add node to parent. 
    // for some calls, the parent will be the head 
} 
+0

Java는 * 값 *을 전달하지만 참조는 전달하지 않습니다. 요점은 자바에서 당신이 실제로 객체의 값을 직접 만지는 일은 결코 없다는 것입니다 (C++에서 할 수있는 것처럼). – oldrinb

2

나는 문제가 "추가"기능을 내부이라고 생각합니다. 함수 범위 안의 "head"값만 변경합니다. Java가 전달 매개 변수 값 here을 처리하는 방법에 대한 유용한 정보를 찾을 수 있습니다.

Java에서 LinkedList의 좋은 구현은 here입니다.

0

링크드 목록을 더 잘 삽입했습니다. 참고 :

  1. _head 개인 회원
  2. 노드해야하는 내부 메커니즘입니다.당신은 당신의 추가 방법에 대한 데이터 매개 변수 대신
  3. 내가 코드에, 간단하면서도 기본을 쓴 노드 객체 구현

    public class LinkedList{ 
    private Node _head; 
    public void add(int data) 
    {    
         //Understand this code! What happens if _head=null?     
         _head=new Node(_head,data); 
         /* 
          //Use the following code for a "Normal" nodes-order 
          if(_head==null) 
           _head=new Node(null,data); 
          else{ 
           Node temp=_head; 
           while(temp.next!=null) 
            temp=temp.next;    
           temp.next=new Node(null,data); 
          } 
         */ 
    } 
    public void traverse() 
    { 
        System.out.println("Linked List:: "); 
        Node temp=_head; 
        while(temp!=null){ 
          System.out.println(" " + temp.data); 
          temp = temp.next; 
        } 
    } 
    public LinkedList(){ 
        _head=null;   //null is our lists anchor 
    } 
    
    public static void main(String args[]) 
    { 
        LinkedList firstList = new LinkedList(); 
    
        firstList.add(5); 
        firstList.traverse(); 
        firstList.add(15); 
        firstList.traverse(); 
        firstList.add(30); 
        firstList.traverse(); 
    
    } 
    

    }

+0

귀하의 연결된 목록이 역 삽입 순서임을 유의하십시오. – oldrinb

+0

주문이 사례는 논리적 인 개념입니다. 정말 당신이 당신의 코드로하고 싶은 것에 달려 있습니다. 다른 옵션도 표시하려면 편집하십시오. –

+0

물론, 저는 여러분의 코드가 다르게 동작한다고 말하고 있습니다. – oldrinb