树形结构的考察在数据结构预算法中一直占有很重要的地位,二叉树的遍历一直是最基本的算法,众所周知,二叉树的遍历主要分为前序、中序、后序这三种,且三种遍历方式都存在递归与非递归两种形式,这里做一下整理与总结。
这里先定义一下二叉树结点的数据结构:
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");
}
运行结果: