本文概述
- C++
- Java
- Python 3
- C#
1. Initialize current as root
2. While current is not NULL
If the current does not have left child
a) Print current’s data
b) Go to the right, i.e., current = current->
right
Else
a) Make current as the right child of the rightmost
node in current's left subtree
b) Go to this left child, i.e., current = current->
left
尽管通过遍历对树进行了修改, 但在完成后将其恢复为原始形状。不像基于栈的遍历, 此遍历不需要额外的空间。
C++
#include <
stdio.h>
#include <
stdlib.h>
/* A binary tree tNode has data, a pointer to left child
and a pointer to right child */
struct tNode {
int data;
struct tNode* left;
struct tNode* right;
};
/* Function to traverse the binary tree without recursion and
without stack */
void MorrisTraversal( struct tNode* root)
{
struct tNode *current, *pre;
if (root == NULL)
return ;
current = root;
while (current != NULL) {if (current->
left == NULL) {
printf ( "%d " , current->
data);
current = current->
right;
}
else {/* Find the inorder predecessor of current */
pre = current->
left;
while (pre->
right != NULL &
&
pre->
right != current)
pre = pre->
right;
/* Make current as the right child of its inorder
predecessor */
if (pre->
right == NULL) {
pre->
right = current;
current = current->
left;
}/* Revert the changes made in the 'if' part to restore
the original tree i.e., fix the right child
of predecessor */
else {
pre->
right = NULL;
printf ( "%d " , current->
data);
current = current->
right;
} /* End of if condition pre->
right == NULL */
} /* End of if condition current->
left == NULL*/
} /* End of while */
}/* UTILITY FUNCTIONS */
/* Helper function that allocates a new tNode with the
given data and NULL left and right pointers. */
struct tNode* newtNode( int data)
{
struct tNode* node = new tNode;
node->
data = http://www.srcmini.com/data;
node->
left = NULL;
node->
right = NULL;
return (node);
}/* Driver program to test above functions*/
int main()
{/* Constructed binary tree is
1
/
23
/
45
*/
struct tNode* root = newtNode(1);
root->
left = newtNode(2);
root->
right = newtNode(3);
root->
left->
left = newtNode(4);
root->
left->
right = newtNode(5);
MorrisTraversal(root);
return 0;
}
Java
// Java program to print inorder traversal without recursion and stack/* A binary tree tNode has data, a pointer to left child
and a pointer to right child */
class tNode {
int data;
tNode left, right;
tNode( int item)
{
data = http://www.srcmini.com/item;
left = right = null ;
}
}class BinaryTree {
tNode root;
/* Function to traverse a binary tree without recursion and
without stack */
void MorrisTraversal(tNode root)
{
tNode current, pre;
if (root == null )
return ;
current = root;
while (current != null ) {
if (current.left == null ) {
System.out.print(current.data +" " );
current = current.right;
}
else {
/* Find the inorder predecessor of current */
pre = current.left;
while (pre.right != null &
&
pre.right != current)
pre = pre.right;
/* Make current as right child of its inorder predecessor */
if (pre.right == null ) {
pre.right = current;
current = current.left;
}/* Revert the changes made in the 'if' part to restore the
original tree i.e., fix the right child of predecessor*/
else {
pre.right = null ;
System.out.print(current.data + " " );
current = current.right;
} /* End of if condition pre->
right == NULL */} /* End of if condition current->
left == NULL*/} /* End of while */
}public static void main(String args[])
{
/* Constructed binary tree is
1
/\
23
/\
45
*/
BinaryTree tree = new BinaryTree();
tree.root = new tNode( 1 );
tree.root.left = new tNode( 2 );
tree.root.right = new tNode( 3 );
tree.root.left.left = new tNode( 4 );
tree.root.left.right = new tNode( 5 );
tree.MorrisTraversal(tree.root);
}
}// This code has been contributed by Mayank Jaiswal(mayank_24)
Python 3
# Python program to do Morris inOrder Traversal:
# inorder traversal without recursion and without stackclass Node:
"""A binary tree node"""
def __init__( self , data, left = None , right = None ):
self .data = http://www.srcmini.com/data
self .left = left
self .right = rightdef morris_traversal(root):"""Generator function for iterative inorder tree traversal"""current = rootwhile current is not None :if current.left is None :
yield current.data
current = current.right
else :# Find the inorder predecessor of current
pre = current.left
while pre.right is not None and pre.right is not current:
pre = pre.rightif pre.right is None :# Make current as right child of its inorder predecessor
pre.right = current
current = current.leftelse :
# Revert the changes made in the 'if' part to restore the
# original tree. i.e., fix the right child of predecessor
pre.right = None
yield current.data
current = current.right# Driver program to test the above function
"""
Constructed binary tree is
1
/\
23
/\
45
"""
root = Node( 1 , right = Node( 3 ), left = Node( 2 , left = Node( 4 ), right = Node( 5 )
)
)for v in morris_traversal(root):
print (v, end = ' ' )# This code is contributed by Naveen Aili
# updated by Elazar Gershuni
C#
// C# program to print inorder traversal
// without recursion and stack
using System;
/* A binary tree tNode has data, pointer to left child
and a pointer to right child */class BinaryTree
{
tNode root;
public class tNode
{
public int data;
public tNode left, right;
public tNode( int item)
{
data = http://www.srcmini.com/item;
left = right = null ;
}
}
/* Function to traverse binary tree without
recursion and without stack */
void MorrisTraversal(tNode root)
{
tNode current, pre;
if (root == null )
return ;
current = root;
while (current != null )
{
if (current.left == null )
{
Console.Write(current.data +" " );
current = current.right;
}
else
{
/* Find the inorder predecessor of current */
pre = current.left;
while (pre.right != null &
&
pre.right != current)
pre = pre.right;
/* Make current as right child
of its inorder predecessor */
if (pre.right == null )
{
pre.right = current;
current = current.left;
}/* Revert the changes made in
if part to restore the original
tree i.e., fix the right child
of predecssor*/
else
{
pre.right = null ;
Console.Write(current.data + " " );
current = current.right;
} /* End of if condition pre->
right == NULL */} /* End of if condition current->
left == NULL*/} /* End of while */
}// Driver code
public static void Main(String []args)
{
/* Constructed binary tree is
1
/ \
23
/ \
45
*/
BinaryTree tree = new BinaryTree();
tree.root = new tNode(1);
tree.root.left = new tNode(2);
tree.root.right = new tNode(3);
tree.root.left.left = new tNode(4);
tree.root.left.right = new tNode(5);
tree.MorrisTraversal(tree.root);
}
}// This code has been contributed
// by Arnab Kundu
输出如下:
4 2 5 1 3
【实现树的中序遍历,无需递归且不使用栈!】时间复杂度:O(n),如果仔细观察, 会发现树的每个边缘最多被遍历两次。在最坏的情况下, 会创建和删除相同数量的额外边(与输入树一样)。
参考文献:
www.liacs.nl/~deutz/DS/september28.pdf
www.scss.tcd.ie/disciplines/software_systems/…/HughGibbonsSlides.pdf
如果你在上述代码/算法中发现任何错误, 或者想共享有关栈Morris有序树遍历的更多信息, 请写评论。
推荐阅读
- JavaScript中如何检查变量是否为数组()
- PHP如何使用Ds\PriorityQueue push()函数(用法示例)
- Perl操作符/运算符用法示例介绍
- PHP如何使用parse_str()函数(用法示例)
- Java中的队列接口Queue的用法详细指南
- PHP GMP函数完整参考
- Python和OpenCV使用带网络摄像头进行人脸检测
- 算法题(找到第n个数字,其数字仅包含为0、1、2、3、4或5)
- 升级GCC,支持C++17