今天介绍一种精妙的无堆栈,O(1)空间的二叉树遍历算法:Morris遍历,它是Morris发明的。
大家都很熟悉用递归和堆栈来实现二叉树的遍历,比如,前序遍历,中序遍历,后序遍历。但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;
}
}
}
}
Template实现:
算法示例:
思考题:
怎么实现Morris前序遍历?后序遍历?