树形结构的考察在数据结构预算法中一直占有很重要的地位,二叉树的遍历一直是最基本的算法,众所周知,二叉树的遍历主要分为前序、中序、后序这三种,且三种遍历方式都存在递归与非递归两种形式,这里做一下整理与总结。
这里先定义一下二叉树结点的数据结构:
struct TreeNode { int val; struct TreeNode* left = NULL; struct TreeNode* right = NULL; TreeNode(int x) { val = x; } };
这里我们使用的树的形式如下:
构建这棵二叉树的代码实现如下:
TreeNode* constructBiTree() { TreeNode a(1); TreeNode b(2); TreeNode c(3); TreeNode d(4); TreeNode e(5); TreeNode f(6); a.left = &b; b.left = &c; a.right = &d; d.left = &e; d.right = &f; return &a; }
(一)先序遍历(Pre-order)
递归定义:
void preorder_recursion(TreeNode* root) { if (!root) { return; } printf("%d", root->val); preorder_recursion(root->left); preorder_recursion(root->right); }
非递归实现(使用一个栈s,每次遍历结点同时,将其非空右指针压入s):
void preorder_loop(TreeNode* root) { std::stack<TreeNode*> s; TreeNode* p = root; while (p || !s.empty()) { if (p) { if (p->right) { s.push(p->right); } std::cout << p->val << ""; p = p->left; } else { TreeNode *node = s.top(); s.pop(); p = node; } } }
编写主程序如下:
int main() { TreeNode a(1); TreeNode b(2); TreeNode c(3); TreeNode d(4); TreeNode e(5); TreeNode f(6); a.left = &b; b.left = &c; a.right = &d; d.left = &e; d.right = &f; TreeNode* biTree = &a; printf("preorder: \n"); preorder_recursion(biTree); printf("\n"); preorder_loop(biTree); printf("\n"); system("pause"); }
运行结果:
(二)中序遍历
递归实现:
void inorder_recursion(TreeNode* root) { if (!root) { return; } inorder_recursion(root->left); std::cout << root->val; inorder_recursion(root->right); }
非递归实现(同样使用一个栈s):
void inorder_loop(TreeNode* root) { std::stack<TreeNode*> s; if (!root) { return; } TreeNode *p = root; while (p || !s.empty()) { if (p) { s.push(p); p = p->left; } else { TreeNode* node = s.top(); std::cout << node->val; s.pop(); p = node->right; } } }
主程序编写:
int main() { TreeNode a(1); TreeNode b(2); TreeNode c(3); TreeNode d(4); TreeNode e(5); TreeNode f(6); a.left = &b; b.left = &c; a.right = &d; d.left = &e; d.right = &f; TreeNode* biTree = &a; printf("inorder: \n"); inorder_recursion(biTree); printf("\n"); inorder_loop(biTree); printf("\n"); system("pause"); }
运行结果:
(后序遍历)
递归实现:
void postorder_recursion(TreeNode* root) { if (!root) { return; } postorder_recursion(root->left); postorder_recursion(root->right); std::cout << root->val; }
非递归实现:
(1)Push根结点到第一个栈s中。
(2)从第一个栈s中Pop出一个结点,并将其Push到第二个栈output中。
(3)然后Push结点的左孩子和右孩子到第一个栈s中。
(4)重复过程2和3直到栈s为空。
(5)完成后,所有结点已经Push到栈output中,且按照后序遍历的顺序存放,直接全部Pop出来即是二叉树后序遍历结果。
void postorder_loop(TreeNode* root) { if (!root) { return; } std::stack<TreeNode*> s, output; s.push(root); while (!s.empty()) { TreeNode *node = s.top(); s.pop(); output.push(node); if (node->left) { s.push(node->left); } if (node->right) { s.push(node->right); } } while (!output.empty()) { TreeNode *node = output.top(); std::cout << node->val; output.pop(); } }
主函数实现:
int main() { TreeNode a(1); TreeNode b(2); TreeNode c(3); TreeNode d(4); TreeNode e(5); TreeNode f(6); a.left = &b; b.left = &c; a.right = &d; d.left = &e; d.right = &f; TreeNode* biTree = &a; printf("postorder: \n"); postorder_recursion(biTree); printf("\n"); postorder_loop(biTree); printf("\n"); system("pause"); }
运行结果: