在去面试之前我正在做一些准备工作,我刚刚了解了 Morris Traversal。
这是我用 Java 编写的 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
这是我的 In-Order 方法的代码:
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");
结果让我吃惊!
这些是结果:
莫里斯遍历 TOOK:637 毫秒
递归有序 TOOK:367 毫秒
注意 - 当我做这个测试时,我评论了来自 morrisTraversal() 和 recInOrderHelper() 方法的所有 System.out.println(...) 。
这些结果让我感到惊讶,因为我认为 Morris Traversal 会更快,因为它的迭代(不打开堆栈帧等)和 In-Order 是递归的(每次递归调用打开大约 70,000,000 个堆栈帧)
我知道它们都是 O(n),所以显然我对某些事情是错误的,但是哪个?我错过了什么?为什么 Morris Traversal 比递归 In-Order 慢得多?
编辑-我还进行了下一个测试:我没有向树中插入 70,000,000 个节点,而是插入了 100,000 个节点并且我确实运行了下一个代码:
//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");
结果是:
递归有序 TOOK:214434 毫秒
莫里斯遍历 TOOK:502786 毫秒
正如您所看到的,与递归 In-Order 相比,Morris Traversal 仍然非常慢。所以我又做了一次测试,只插入了 1000 个节点,每个代码只运行了 10000 次,结果是:
递归有序 TOOK:44 毫秒
莫里斯遍历 TOOK:97 毫秒
我还是不明白?为什么莫里斯遍历速度较慢?