2013-02-06 2 views
0

나는 인터뷰에 가기 전에 몇 가지 준비를하고 있으며, Morris Traversal에 대해 방금 배웠습니다.Morris Traversal의 성능과 이진 트리의 순차적 순회 비교

이 내가 자바 (그 작업)에 쓴 모리스 순회 코드 :

protected void morrisTraversal(){ 
    BinaryNode pre = null;//BinaryNode is a class which represent a node in the tree 
    BinaryNode current = this.root;//root is the root of the tree 
    while(current != null){ 
     if(current.getLeftChild() == null){ 
      System.out.println(current.getNodeData().getId());//id is unique 
      current = current.getRightChild(); 
     }//if 
     else{ 
      pre = current.getLeftChild(); 
      while(pre.getRightChild() != null && pre.getRightChild().getNodeData().getId() != current.getNodeData().getId()) 
       pre = pre.getRightChild(); 
      if(pre.getRightChild() == null){ 
       pre.setRightChild(current); 
       current = current.getLeftChild(); 
      }//if 
      else{ 
       System.out.println(current.getNodeData().getId()); 
       current = current.getRightChild(); 
       pre.setRightChild(null); 
      }//else 
     }//else 
    }//while 
}//MorrisTraversal 

그리고 여기가에서 주문 방법에 대한 내 코드입니다 :

protected void recInOrder() { 
    if(this.root != null) 
     recInOrderHelper(this.root); 
    else 
     System.out.println("The Tree Is Empty");; 
}//recInOrder 


private void recInOrderHelper(BinaryNode node) { 
    if(node != null){ 
     recInOrderHelper(node.getLeftChild()); 
     System.out.println(node.getNodeData().getId()); 
     recInOrderHelper(node.getRightChild()); 
    } 
}//recInOrderHelper 

그리고 내가에서 한 내 주요입니다 내 이진 트리에 70,000,000 노드를 삽입하고 난 다음 작은 검사했다 :

long start = System.currentTimeMillis(); 
tree4.morrisTraversalInOrder(); 
System.out.println("morris traversal TOOK: " + (System.currentTimeMillis() - start) + " ms"); 

start = System.currentTimeMillis(); 
tree4.recInOrder(); 
System.out.println("recursive in-order TOOK: " + (System.currentTimeMillis() - start) + " ms"); 
을 0

그리고 결과는 나를 놀라게했다! 나는 모든 System.out에 댓글을 달았이 테스트를했을 때 - 367 MS

주의 사항 :

모리스 순회 걸린 : 637 MS

재귀에서 주문 걸린

결과입니다 morrisTraversal() 및 recInOrderHelper() 메소드의 .println (...). 내가과에서 주문이 재귀 반복 (금지 스택 프레임 등을한다) 그 때문에 모리스 순회은 (각 재귀 호출에 대해 약 70,000,000 스택 프레임을 엽니 다) 더 빠를 것이라고 생각했기 때문에

그 결과는 나를 놀라게

나는 둘 다 O (n) 인 것을 안다. 그래서 분명히 나는 ​​어떤 것들에 대해서는 틀렸다. 그러나 그것은 무엇인가? 내가 뭘 놓치고 있니? Morris Traversal이 반복적 인 In-Order보다 왜 훨씬 느린가요? -

편집 나는 또한 다음 시험했다 : 트리에 70,000,000 노드를 삽입하는 대신 나는 10 만 개 노드 을 삽입 그리고 나는 다음 코드를 실행 않았다

//running the two algorithms one time before doing the actual test(but in the same execution) 
tree4.recInOrder(); 
tree4.morrisTraversalInOrder(); 

//starting the actual test 
long start = System.currentTimeMillis(); 
for(i = 0; i < 100000; i++){ 
    tree4.recInOrder(); 
} 
System.out.println("Recursive In-Order TOOK: " + (System.currentTimeMillis() - start) + " ms"); 

start = System.currentTimeMillis(); 
for(i = 0; i < 100000; i++){ 
    tree4.morrisTraversalInOrder(); 
} 
System.out.println("Morris Traversal TOOK: " + (System.currentTimeMillis() - start) + " ms"); 

을 그리고 그 결과는 다음과 같습니다

재귀 인 - 주문에 나섭니다 : 214434 MS

모리스 순회가 나섭니다 : 502786 MS

Morris Traversal은 반복적 인 In-Order에 비해 여전히 매우 느린 것을 볼 수 있습니다. 그래서 나는 또 다른 테스트를했다 만 1,000 노드를 삽입 10,000 회 그 결과는 각각의 코드를 실행 :

재귀 인 - 주문에 나섭니다 : 44 MS

모리스 순회가 나섭니다 : 97 MS

나는 아직도 그것을 얻지 못합니까? Morris Traversal이 왜 더 느린가요?

+0

누군가가 왜 Morris Traversal이 더 느린 지 설명 할 수 있습니까? – thelegend

답변

0

성능 평가를 구성 요소에 적용하지 않고 말하기는 어렵지만 모리스 탐색은 본질적으로 가짜 오른쪽 부분으로 노드를 추적 할 때 트리의 일부를 두 번 통과합니다. 모리스 루프 내부에서 더 많은 작업을하고 있기 때문에 상수 요소가 커질 수 있습니다.그것은 거의 2 배이지만, 나는 세부 사항없이 실제 비용이라는 것에 의존하지 않을 것입니다.

0

워밍업 패스가 없습니다. 먼저 두 방법을 모두 실행 한 다음 타이밍에 따라 다시 실행해야합니다. 또한 대부분의 Java 코드가 장기 실행 프로세스에서 실행되므로 결국 머신 코드로 컴파일된다는 사실을 무시하고 있습니다. 더 작은 트리를 사용하고 여러 번 탐색을 시도 할 것입니다.