Morris 遍历,使用无堆栈,O(1) 空间进行二叉树遍历。它的原理很简单,利用所有叶子结点的右指针,指向其后继结点,组成一个环,在第二次遍历到这个结点时,由于其左子树已经遍历完了,则访问该结点。
算法伪码:
MorrisInOrder():
while 没有结束
如果当前节点没有左后代
访问该节点
转向右节点
否则
找到左后代的最右节点,且使最右节点的右指针指向当前节点
转向左后代节点
C++实现:
void bst_morris_inorder(struct bst_node *root) {
struct bst_node *p = root, *tmp;
while (p) {
if (p->left == NULL) {
printf("%d ", p->key);
p = p->right;
}
else {
tmp = p->left;
while (tmp->right != NULL && tmp->right != p)
tmp = tmp->right;
if (tmp->right == NULL) {
tmp->right = p;
p = p->left;
}
else {
printf("%d ", p->key);
tmp->right = NULL;
p = p->right;
}
}
}
}
java 实现:
public class MorrisTree {
public static void main(String[] args) {
Tree t = new Tree();
t = t.make();
t.printTree();
}
}
class Tree{
private Node root;
private class Node{
private String value;
private Node left, right;
public Node(String value, Node left, Node right) {
this.value = value;
this.left = left;
this.right = right;
}
}
public Tree make() {
Tree t = new Tree();
t.root = new Node("F", null, null);
t.root.left = new Node("B", new Node("A", null, null),
new Node("D", new Node("C", null, null), new Node("E", null, null)));
t.root.right = new Node("G", null, new Node("I", new Node("H", null, null), null));
return t;
}
void printTree() {
Tree t = make();
System.out.println("普通中序遍历结果:");
middleOrder(t.root);
System.out.println();
System.out.println("Morris中序遍历结果:");
morris_inorder(t.root);
//middleOrder(t.root);
}
private void middleOrder(Node root) {
if(root.left != null)
middleOrder(root.left);
System.out.print(root.value + " ");
if(root.right != null)
middleOrder(root.right);
}
public void morris_inorder(Node root) {
while(root != null) {
if(root.left != null) {
Node temp = root.left;
while(temp.right != null && temp.right != root) {
temp = temp.right;
}
if(temp.right == null) {
temp.right = root;
root = root.left;
} else {
System.out.print(root.value + " ");
temp.right = null;
root = root.right;
}
} else {
System.out.print(root.value + " ");
root = root.right;
}
}
}
}