二叉树遍历的三种方法(以中序为例)

 

 二叉树遍历的三种方法

递归 简单 时间O(n) 空间O(n)
非递归+栈 中等 时间O(n) 空间O(n)
非递归、不用栈 中等 时间O(n) 空间O(1)

 

伪代码实现--近C++代码

方法一:递归

1 Inorder-Tree-Walk(x)
2     if(x != NULL)
3         Inorder-Tree-Walk(x->left)
4         print x->key
5         Inorder-Tree-Walk(x->right)

方法二:非递归+栈

 1 Inorder-Tree-Walk(x)
 2     stack<Node*> s //定义装二叉树节点指针的栈容器
 3         while(x != NULL || !s.empty())
 4              if(x != NULL)
 5                  s.push(x)
 6                  x = x->left
 7              else if(!s.empty())
 8                  x = s.top()
 9                  s.pop()
10                  print x->key
11                  x = x->right  

方法三:非递归,不用栈(Morris 中序遍历[1])

思想:利用线索二叉树的思想,无右子树的节点的空闲的右指针,指向此节点中序遍历的后继,以此记录在此节点之后要访问的点。要使得无右子树的节点指向后继,不直接计算其后继,而是迭代地计算所经过的节点的前驱(左子树的最右节点)。

 1 Inorder-Tree-Walk(x)
 2     Node *cur = x, *prev;
 3     while(cur != NULL)
 4         if(cur->left != NULL)  //如果左子树不为空,不应打印当前节点,需在当前节点的前驱节点记录下此节点(此节点记录在其前驱的右指针,其前驱右指针原本一定为空),方便下次找到这个节点。
 5             //试图找到当前节点的中序序列前驱,前驱在左子树的最右点
 6             prev = cur->left  //先使prev为左子树根节点
 7             while(prev->right != NULL && prev->right != cur)
 8                 prev = prev->right
 9             //第一次找到左子树最右点时,最右点的右指针肯定为空,但是此时将标记其右指针指向该节点的后继(cur 节点),那么第二次到cur时,将再次执行找到其前驱。如果在寻找其前驱的过程中发现:有一个节点指向cur。说明这是第二次访问这个节点(cur的前驱已经打印输出,该cur输出了),这也是为什么找前驱的while里需要判断“prev->right != cur”。
10             if(prev->right == NULL) //第一次找到cur的前驱prev
11                 prev->right = cur   //标记其右指针指向cur,因为cur还没有输出,在输出prev后,输出cur
           cur = cur->left //转向左节点,继续循环
12 else // 第二次找到cur的前驱,此时prev->right == cur。第二次到达cur节点,一定是从其前驱的右指针过来的,说明其前驱已经输出打印完毕,该打印cur了 13 print cur->key
           prev->right = NULL //将原先的标记(右指针指向后继)清除
14 cur = cur->right //往右走,其左子树和当前节点已经遍历完成,继续循环 15 else //cur->left == NULL, 如果左子树为空,打印输出当前节点 16 print cur->key 17 cur = cur->right //转向右节点,继续循环


参考资料:[1]
http://www.cnblogs.com/AnnieKim/archive/2013/06/15/morristraversal.html Accessed at 2015/4/11
     [2] 《算法导论》中文版 原书第三版 机械工业出版社

posted @ 2015-04-11 14:31  Eastern Sunrise  阅读(2316)  评论(2编辑  收藏  举报