2013-05-10 1 views
1

정렬 된 연결 목록을 균형 잡힌 BST로 변환하기 위해 Java에서이 코드를보고 있었고 구현 # 1이 작동하지 않는 이유를 알고 싶었습니다. 래퍼 객체를 생성하고 전달할 때 자바가 사용하는 이유는 무엇인가? 완벽하게 작동하지만 로컬 참조를 사용할 때 나던가? 개체는 여전히 힙 오른쪽에 만들어집니다.로컬 참조를 전달하는 대신 래퍼 객체를 Java에서 작동시키는 이유는 무엇입니까?

구현 # 1

BinaryTree.Node sortedListToBST(MyList.Node w, int start, int end) 
    { 
      if (start > end) return null; 
      int mid = start + (end - start)/2; 
      BinaryTree.Node left = sortedListToBST(w, start, mid-1); 
      BinaryTree.Node parent = new BinaryTree.Node(w.getVal()); 
      w = w.getNext(); 
      BinaryTree.Node right = sortedListToBST(w, mid+1, end); 
      parent.left = left; 
      parent.right =right; 
      return parent; 
     } 



     BinaryTree.Node sortedListToBST(MyList.Node head, int n) { 

      return sortedListToBST(head, 0, n-1); 
     } 

구현 # 2

BinaryTree.Node sortedListToBSTWrapper(Wrapper w, int start, int end) 
    { 
      if (start > end) return null; 
      int mid = start + (end - start)/2; 
      BinaryTree.Node left = sortedListToBSTWrapper(w, start, mid-1); 
      BinaryTree.Node parent = new BinaryTree.Node(w.node.getVal()); 
      w.node = w.node.getNext(); 
      BinaryTree.Node right = sortedListToBSTWrapper(w, mid+1, end); 
      parent.left = left; 
      parent.right =right; 
      return parent; 
     } 



     BinaryTree.Node sortedListToBSTWrapper(MyList.Node head, int n) { 
      Wrapper w = new Wrapper(); 
       w.node = head; 
      return sortedListToBSTWrapper(w, 0, n-1); 
     } 

답변

4

핵심 라인이다 : 첫 번째 구현에서

w.node = w.node.getNext(); 

, 재귀 수준에서 '발전 포인터' 잊혀진다; 학부모 방문자는 진급 된 직위를 보지 못합니다.

첫 번째 접근 방식을 사용하려면 Iterator를 가지고 다니거나 포함하는 클래스에 일종의 반복자를 구현해야합니다. 그러면 LHS를 작성하는 동안 소스 목록을 통해 향상시킬 수 있습니다. 조부모 등에 반환되기 전에 RHS를 작성하는 데 사용 된 부모 &으로 돌아갑니다.

언어에 다중 값이 반환되면 필드에서 작업 진행 상황을 추적 할 수 있습니다.

기본적으로 이미 솔루션을 해킹 한 - 그것은 깨끗합니다 & 구조화되지 않은 것은 당신이 단지로 찾으면 반대로 당신이 반복자 (W) 할 경우 올바른.

+0

토마스, 개체가 힙에 만들어진 경우 부모가 고급 포인터를 보지 않는 이유는 무엇입니까? – Phoenix

+0

그리고 이전 재귀 호출에서 볼 수있는 다른 객체 참조를 포함하는 래퍼의 로컬 참조를 전달하는 이유는 무엇입니까? – Phoenix

+0

둘 다 스택 프레임의 참조입니까? 그렇다면 왜 두 번째 접근법이 일을 올바르게 보는가? 두 가지 모두 로컬 참조인데도 메모리가 다르게 액세스되는 방법에 대한 답을 설명 할 수 있습니까? – Phoenix

0

노드를 래퍼에 넣고 래퍼를 전달하면 모두에게 동일한 래퍼가 있으며 내부 노드가 변경되면 래퍼의 모든 사람들이 래퍼를 볼 수 있습니다. n.node가 변경되면 모두에게 변경된 노드가 표시됩니다.

노드에 직접 참조를 전달하면 절대 변경되지 않습니다. 함수 호출 MyList.Node node는 항상 정확히 하나 개의 장소를 가리키는, 결코

그것은 많은 같은 유용한 Wrapper 뭔가 currentWorkNode 이름을 도움이 변경되지 않습니다. 또한 Wrapper을 사용한이 구현은 병렬 처리 환경에서 매우 안전하지 않을 것입니다 ... 재귀가 병렬 처리에 적합하기 때문에 불행합니다.

관련 문제