# 二叉树遍历之morris traversal

morris 中序遍历

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;
}
}
}
}

morris traversal 原理很简单，利用所有叶子结点的right 指针，指向其后继结点，组成一个环，在第二次遍历到这个结点时，由于其左子树已经遍历完了，则访问该结点

morris 前序遍历

void bst_morris_preorder(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) {
printf("%d ", p->key);
tmp->right = p;
p = p->left;
}
else {
tmp->right = NULL;
p = p->right;
}
}
}
}


morris 后序遍历

static void bst_morris_reverse(struct bst_node *node, struct bst_node *last)
{
struct bst_node *p = node, *x, *y;
if (p == last) {
printf("%d ", last->key);
return;
}

/* change right to parent pointer */
x = p->right;
for (;;) {
if (x == last) {
x->right = p;
break;
}
y = x->right;
x->right = p;
p = x;
x = y;
}

/* visit each */
x = last;
for (;;) {
printf("%d ", x->key);
if (x == node)
break;
x = x->right;
}

/* revert right pointer */
p = last;
x = last->right;
for (;;) {
if (x == node) {
x->right = p;
break;
}
y = x->right;
x->right = p;
p = x;
x = y;
}
}

void bst_morris_postorder(struct bst_node *root)
{
struct bst_node dummy;
struct bst_node *p, *tmp;

dummy.left = root;
dummy.right = NULL;
p = &dummy;

while (p) {
if (p->left == NULL) {
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 {
bst_morris_reverse(p->left, tmp);
tmp->right = NULL;
p = p->right;
}
}
}
}