Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 二叉树中Morris遍历与递归顺序的性能_Java_Performance_Binary Tree_Tree Traversal_Inorder - Fatal编程技术网

Java 二叉树中Morris遍历与递归顺序的性能

Java 二叉树中Morris遍历与递归顺序的性能,java,performance,binary-tree,tree-traversal,inorder,Java,Performance,Binary Tree,Tree Traversal,Inorder,在去面试之前,我正在做一些准备,我刚刚了解了莫里斯·特拉弗斯 这是我用Java编写的Morris Traversal代码(其工作原理): 下面是我的顺序方法代码: protected void recInOrder() { if(this.root != null) recInOrderHelper(this.root); else System.out.println("The Tree Is Empty");; }//recInOrder

在去面试之前,我正在做一些准备,我刚刚了解了莫里斯·特拉弗斯

这是我用Java编写的Morris Traversal代码(其工作原理):

下面是我的顺序方法代码:

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
我主要做的是: 我在我的二叉树中插入了7000000个节点,然后进行了下一个小检查:

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");
结果让我大吃一惊

结果如下:

莫里斯穿越时间:637毫秒

按顺序递归:367毫秒

注意-当我进行此测试时,我对morrisTraversal()和RecinonderHelper()方法中的所有System.out.println(…)进行了注释。

这些结果让我惊讶,因为我认为Morris遍历会更快,因为它是迭代的(不打开堆栈帧等),顺序是递归的(为每个递归调用打开大约7000000个堆栈帧)

我知道他们都是O(n), 很明显,我在某些事情上是错的,但哪一个呢?我错过了什么?为什么Morris遍历要比顺序递归慢得多

编辑-我还做了下一个测试: 我没有向树中插入7000000个节点,而是插入100000个节点 我确实运行了下一个代码:

//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");
//在执行实际测试之前(但在同一执行中)运行两个算法一次
tree4.recinoder();
tree4.morris顺序();
//开始实际测试
长启动=System.currentTimeMillis();
对于(i=0;i<100000;i++){
tree4.recinoder();
}
System.out.println(“按顺序递归:”+(System.currentTimeMillis()-start)+“ms”);
start=System.currentTimeMillis();
对于(i=0;i<100000;i++){
tree4.morris顺序();
}
System.out.println(“Morris Traversal take:”+(System.currentTimeMillis()-start)+“ms”);
结果是:

递归顺序:214434毫秒

Morris Traversal拍摄时间:502786毫秒

正如你们所看到的,莫里斯遍历和按顺序递归相比仍然非常慢。 所以我做了另一个测试,只插入了1000个节点,每个代码只运行了10000次 结果是:

按顺序递归:44毫秒

莫里斯穿越时间:97毫秒


我还是不明白?为什么Morris遍历速度较慢?

如果不将性能评估分解为它们的组件,很难说出来,但是Morris遍历本质上是在使用伪右侧部分跟踪节点时遍历树的一部分两次。你在Morris循环中也做了更多的功,所以常数因子会更大。奇怪的是,它几乎是2倍,但如果没有进一步的细节,我不会相信这是实际成本。

你没有热身通行证。您应该首先执行这两个方法,然后再定时执行它们。您还忽略了一个事实,即大多数Java代码都在长时间运行的进程中运行,这些进程最终会编译成机器代码。我会尝试使用较小的树并多次执行遍历。

请看这里,您必须理解逻辑。只需对莫里斯进行试运行,以便遍历,比如说需要时间2k。现在进行递归顺序遍历的试运行,我非常确定您将发现时间或多或少为k。 这里的逻辑是Morris索引遍历所花费的时间是索引遍历所花费时间的两倍,因为我们最多到达每个节点2次。一次用于创建虚拟右链接,另一次用于删除该右链接

现在,如果你对空间复杂性感兴趣,那么莫里斯顺序遍历就像一个国王。这里你不需要额外的空间。它的空间复杂度为O(1),而递归序遍历的空间复杂度为O(n)。
希望您现在能够理解这两种遍历策略的用法。:)

有人能解释为什么Morris遍历较慢?
//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");