Binary Tree Traversal Algorithms (二叉树遍历算法)

本文共列出了11个常见的二叉树遍历算法。二叉树的遍历主要有深度优先遍历和广度优先遍历。深度优先遍历包含前序遍历、中序遍历和后序遍历。

值得一提的是, 其中的 Morris 算法 可以线性时间不需要额外空间(用户栈或系统栈空间)实现二叉树的前序遍历、中序遍历和后序遍历。关于Morris算法, 可参考 http://www.cnblogs.com/AnnieKim/archive/2013/06/15/morristraversal.html

算法清单:

  A1、 A2、 A3, 分别是中序遍历的递归、迭代、和Morris算法实现。

  A4、 A5、 A6, 分别是前序遍历的递归、迭代、和Morris算法实现。

  A7、 A8、 A9, 分别是后序遍历的递归、迭代、和Morris算法实现。

  A10 是广度优先遍历算法实现。

  A11 ZigZag顺序的遍历算法。

C++源代码:

  1 #include <iostream>
  2 #include <stack>
  3 #include <queue>
  4 using namespace std;
  5
  6 struct bt_node {
  7     int value;
  8     bt_node *left, *right;
  9     bt_node(int val = 0)
 10         : value(val), left(NULL), right(NULL) {}
 11 };
 12
 13 void process(bt_node* pnode) {
 14     if (pnode != NULL)
 15         cout << pnode->value << " ";
 16 }
 17
 18 // A1
 19 void recursive_inorder_traversal(bt_node* root) {
 20     if (root != NULL) {
 21         recursive_inorder_traversal(root->left);
 22         process(root);
 23         recursive_inorder_traversal(root->right);
 24     }
 25 }
 26
 27 // A2
 28 void iterative_inorder_traversal(bt_node* root) {
 29     stack<bt_node*> _stack;
 30     bt_node* p = root;
 31     while (p != NULL) {
 32         while (p != NULL) {
 33             _stack.push(p);
 34             p = p->left;
 35         }
 36         p = _stack.top();
 37         _stack.pop();
 38         process(p);
 39         while (p->right == NULL && !_stack.empty()) {
 40             p = _stack.top();
 41             _stack.pop();
 42             process(p);
 43         }
 44         p = p->right;
 45     }
 46 }
 47
 48 // A3
 49 void morris_inorder_traversal(bt_node* root) {
 50     bt_node* p = root;
 51     while (p != NULL) {
 52         if (p->left == NULL) {
 53             process(p);
 54             p = p->right;
 55         } else {
 56             bt_node* tmp = p->left;
 57             while (tmp->right != NULL && tmp->right != p) {
 58                 tmp = tmp->right;
 59             }
 60             if (tmp->right == NULL) {
 61                 tmp->right = p;
 62                 p = p->left;
 63             } else {
 64                 tmp->right = NULL;
 65                 process(p);
 66                 p = p->right;
 67             }
 68         }
 69     }
 70 }
 71
 72 // A4
 73 void recursive_preorder_traversal(bt_node* root) {
 74     if (root != NULL) {
 75         process(root);
 76         recursive_preorder_traversal(root->left);
 77         recursive_preorder_traversal(root->right);
 78     }
 79 }
 80
 81 // A5
 82 void iterative_preorder_traversal(bt_node* root) {
 83     stack<bt_node*> _stack;
 84     bt_node* p = root;
 85     while (p != NULL) {
 86         while (p != NULL) {
 87             process(p);
 88             _stack.push(p);
 89             p = p->left;
 90         }
 91         p = _stack.top();
 92         _stack.pop();
 93         while (p->right == NULL && !_stack.empty()) {
 94             p = _stack.top();
 95             _stack.pop();
 96         }
 97         p = p->right;
 98     }
 99 }
100
101 // A6
102 void morris_preorder_traversal(bt_node* root) {
103     bt_node* p = root;
104     while (p != NULL) {
105         if (p->left == NULL) {
106             process(p);
107             p = p->right;
108         } else {
109             bt_node* tmp = p->left;
110             while (tmp->right != NULL && tmp->right != p)
111                 tmp = tmp->right;
112             if (tmp->right == NULL) {
113                 tmp->right = p;
114                 process(p);
115                 p = p->left;
116             } else {
117                 tmp->right = NULL;
118                 p = p->right;
119             }
120         }
121     }
122 }
123
124
125 // A7
126 void recursive_postorder_traversal(bt_node* root) {
127     if (root != NULL) {
128         recursive_postorder_traversal(root->left);
129         recursive_postorder_traversal(root->right);
130         process(root);
131     }
132 }
133
134 // A8
135 void iterative_postorder_traversal(bt_node* root) {
136     stack<bt_node*> _stack;
137     bt_node *p = root, *q = NULL;
138     while (p != NULL) {
139         _stack.push(p);
140         p = p->left;
141     }
142     while (!_stack.empty()) {
143         p = _stack.top();
144         if (p->right == NULL || p->right == q) {
145             _stack.pop();
146             process(p);
147             q = p;
148         } else {
149             p = p->right;
150             while (p != NULL) {
151                 _stack.push(p);
152                 p = p->left;
153             }
154         }
155     }
156 }
157
158 bt_node* reverse(bt_node* pnode) {
159     bt_node aux_node;
160     bt_node* p = &aux_node;
161     bt_node* q = pnode;
162     while (q != NULL) {
163         bt_node* next = q->right;
164         q->right = p->right;
165         p->right = q;
166         q = next;
167     }
168     return p->right;
169 }
170
171 void process_in_reverse_order(bt_node* pnode) {
172     pnode = reverse(pnode);
173     bt_node* p = pnode;
174     while (p != NULL) {
175         process(p);
176         p = p->right;
177     }
178     reverse(pnode);
179 }
180
181 // A9
182 void morris_postorder_traversal(bt_node* root) {
183     bt_node dummy;
184     dummy.left = root;
185     bt_node *p = &dummy;
186     while (p != NULL) {
187         if (p->left == NULL) {
188             p = p->right;
189         } else {
190             bt_node* tmp = p->left;
191             while (tmp->right != NULL && tmp->right != p)
192                 tmp = tmp->right;
193             if (tmp->right == NULL) {
194                 tmp->right = p;
195                 p = p->left;
196             } else {
197                 tmp->right = NULL;
198                 process_in_reverse_order(p->left);
199                 p = p->right;
200             }
201         }
202     }
203 }
204
205 // A10
206 void breadth_first_traversal(bt_node* root) {
207     queue<bt_node*> _queue;
208     _queue.push(root);
209     while (!_queue.empty()) {
210         bt_node* p = _queue.front();
211         _queue.pop();
212         process(p);
213         if (p->left != NULL) {
214             _queue.push(p->left);
215         }
216         if (p->right != NULL) {
217             _queue.push(p->right);
218         }
219     }
220 }
221
222 // A11
223 void zigzag_order_traversal(bt_node* root) {
224     stack<bt_node*> _stack1;
225     stack<bt_node*> _stack2;
226     _stack1.push(root);
227     int left_first = 1;
228     while (!_stack1.empty()) {
229         while (!_stack1.empty()) {
230             bt_node* p = _stack1.top();
231             _stack1.pop();
232             process(p);
233             if (left_first) {
234                 if (p->left != NULL)
235                     _stack2.push(p->left);
236                 if (p->right != NULL)
237                     _stack2.push(p->right);
238             } else {
239                 if (p->right != NULL)
240                     _stack2.push(p->right);
241                 if (p->left != NULL)
242                     _stack2.push(p->left);
243             }
244         }
245         left_first = left_first ^ 0x01;
246         _stack1.swap(_stack2); // C++11 Standard
247     }
248 }
249
250 // Test
251 int main() {
252     const int n = 7;
253     bt_node* ptr[n];
254     for (int i = 0; i < n; i++) {
255         ptr[i] = new bt_node(i+1);
256     }
257     ptr[0]->left = ptr[1];
258     ptr[0]->right = ptr[2];
259     ptr[1]->left = ptr[3];
260     ptr[1]->right = ptr[4];
261     ptr[2]->left = ptr[5];
262     ptr[4]->left = ptr[6];
263
264     /*
265      *             1
266      *           /   267      *          2     3
268      *         / \   /
269      *        4   5 6
270      *           /
271      *          7
272      */
273
274     recursive_inorder_traversal(ptr[0]);
275     cout << endl;
276     iterative_inorder_traversal(ptr[0]);
277     cout << endl;
278     morris_inorder_traversal(ptr[0]);
279     cout << endl;
280
281     recursive_preorder_traversal(ptr[0]);
282     cout << endl;
283     iterative_preorder_traversal(ptr[0]);
284     cout << endl;
285     morris_preorder_traversal(ptr[0]);
286     cout << endl;
287
288     recursive_postorder_traversal(ptr[0]);
289     cout << endl;
290     iterative_postorder_traversal(ptr[0]);
291     cout << endl;
292     morris_postorder_traversal(ptr[0]);
293     cout << endl;
294
295     breadth_first_traversal(ptr[0]);
296     cout << endl;
297     zigzag_order_traversal(ptr[0]);
298     cout << endl;
299
300     for (int i = 0; i < n; i++) {
301         delete ptr[i];
302     }
303     return 0;
304 }

程序输出:

4 2 7 5 1 6 3
4 2 7 5 1 6 3
4 2 7 5 1 6 3
1 2 4 5 7 3 6
1 2 4 5 7 3 6
1 2 4 5 7 3 6
4 7 5 2 6 3 1
4 7 5 2 6 3 1
4 7 5 2 6 3 1
1 2 3 4 5 6 7
1 3 2 4 5 6 7
时间: 2024-10-29 19:11:46

Binary Tree Traversal Algorithms (二叉树遍历算法)的相关文章

【LeetCode-面试算法经典-Java实现】【226-Invert Binary Tree(反转二叉树)】

[226-Invert Binary Tree(反转二叉树)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 代码下载[https://github.com/Wang-Jun-Chao] 原题 Invert a binary tree. 4 / 2 7 / \ / 1 3 6 9 to 4 / 7 2 / \ / 9 6 3 1 题目大意 将一棵二叉树进行翻转. 解题思路 对每一个结点,将它的左右子树进行交换,再对它的左右子结点进行同样的操作. 代码实现 树结点类 pub

C++ Binary Tree Traversal

关于二叉树的遍历有很多的方法, 下面介绍两个经典的遍历算法: BFS和DFS.一个是深度优先遍历, 一个是广度有优先遍历. 这两种遍历算法均属于盲目的遍历算法, 一般而言, 启发式的遍历搜索算法比较好一些. . 关于各种遍历算法的对比, 将会在后面逐一提及. 这里不在赘述. 由于树是一个非线性的数据结构, 显然不能像linked list , 或者Array那样通过从头像最末尾移动去实现遍历每一个元素, 我们使用的是BFS和DFS算法. 例如下面的一个二叉树: 所谓的树遍历(Tree trave

hdu 1701 (Binary Tree Traversals)(二叉树前序中序推后序)

Binary Tree Traversals Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description A binary tree is a finite set of vertices that is either empty or consists of a root r and two disjoint binary trees called

morris算法-----高级二叉树遍历算法

在遍历儿叉树时,常常使用的是递归遍历,或者是借助于栈来迭代,在遍历过程中,每个节点仅访问一次,所以这样遍历的时间复杂度为O(n),空间复杂度为O(n),并且递归的算法易于理解和实现.在遍历过程中,递归遍历过程的空间复杂度却是O(n),就算是转换为使用栈空间迭代时间,还是没有改变算法对额外空间的需求,在学习数据结构课程时,还学习了线索二叉树,在线索二叉树中,使用线索来保存节点的前驱和后继的信息,而这些线索是利用了叶节点的空指针域来保存,所以知道了树种每个节点的前驱和后继的位置(指针)可以有效降低遍

二叉树遍历算法总结

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??二叉树遍历算法总结 ? ?? ? ?本文依据<数据结构与算法>(C语言版)(第三版) 整理. ? ?A. ?二叉树的遍历 ? ? ? 1.前序遍历二叉树: ? ? ? ? (1)若二叉树为空,则为空操作,返回空. ? ? ? ? (2)訪问根结点. ? ? ? ? (3)前序遍历左子树. ? ? ? ? (4)前序遍历右子树. ? ? ??a.

LeetCode 257. Binary Tree Paths (二叉树路径)

Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 / 2 3 5 All root-to-leaf paths are: ["1->2->5", "1->3"] 题目标签:Tree 这道题目给了我们一个二叉树,让我们记录所有的路径,返回一个array string list. 我们可以另外设一个fin

LeetCode—— Binary Tree Traversal

二叉树遍历的三道题 Binary Tree Preorder Traversal Binary Tree Inorder Traversal Binary Tree Postorder Traversal LeetCode 上二叉树的节点定义如下: // 树的节点 struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {

【Leetcode】Binary Tree Traversal

把三个二叉树遍历的题放在一起了. 递归写法太简单,就不再实现了,每题实现了两种非递归算法. 一种是利用栈,时间和空间复杂度都是O(n). 另一种是借助线索二叉树,也叫Morris遍历,充分利用树中节点的空指针域. 先序: Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binary tree {1,#,

1102. Invert a Binary Tree (25)【二叉树】——PAT (Advanced Level) Practise

题目信息 1102. Invert a Binary Tree (25) 时间限制400 ms 内存限制65536 kB 代码长度限制16000 B The following is from Max Howell @twitter: Google: 90% of our engineers use the software you wrote (Homebrew), but you can't invert a binary tree on a whiteboard so fuck off.