二叉树概念
二叉树遍历方式
广度优先遍历(层序遍历)
规则:从上往下对每一层操作,在每一层中,从左至右访问节点
上图遍历结果:root->A->B->C->D->E
注意:对于层序遍历方式,一般借助队列来实现。
如题剑指offer:从上往下打印二叉树
深度优先遍历
规则:对每一个可能的分支路径深入到尽头为止,且每个节点之访问一次。注意:二叉树的深度优先遍历可细分为先序,中序,后序遍历。
先序遍历:对任一子树,先访问根,然后遍历其左子树,最后遍历其右子树。
中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树。
后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。
上图遍历结果:
先序:root->A->C->D->B->E
中序:C->A->D->root->B->E
后序:C->D->A->E->B->root
注意:对于以上三种深度优先遍历方式,可采用递归实现,也可采用栈实现,因为递归的本质就是压栈和出栈。
例子
先序遍历-栈实现:
根据先序的规则,使用一个栈s保存待访问的节点,使用p保存当前正在访问的节点,p从根节点开始。一路沿着左子树向下走,直到p为空时,在通过栈进行回退。
根左右:在指针迭代时访问节点值。
void PreShow2(TreeNode* root) //先序栈
{
if(!root) return;
stack<TreeNode*> s;
TreeNode *p = root;
while (p != nullptr|| !s.empty())
{
while(p) //沿着左子树往下走,访问途中节点并压栈保存。
{
cout<<p->val<<' ';
s.push(p);
p = p->left;
}
p = s.top(); //将父节点出栈,并访问其右子树
s.pop();
p=p->right;
}
}
中序遍历-栈实现:
算法思想同先序。
左根右:在栈顶访问结点值
沿着左子树到底,此时只是将途中节点压栈保存,不访问。直至p为空,访问此时栈顶元素
void InShow2(TreeNode*root) //中序栈
{
if(!root) return;
stack<TreeNode*> s;
TreeNode *p = root;
while(p!=nullptr || !s.empty())
{
while(p)
{
s.push(p);
p=p->left;
}
p=s.top();//此时访问父节点元素,并将父节点出栈。
cout<<p->val<<' ';
s.pop();
p=p->right;
}
}
后序遍历-栈实现
后序遍历相对复杂一点,因为后序是左根右,在使用栈来存储节点时,需要分清楚出栈时的节点是从左子树返回的还是右子树返回的。所以需要一个temp表示p上一次表示的节点。
void PostShow2(TreeNode*root) //后序栈
{
if(!root) return;
stack<TreeNode*> s;
TreeNode *p = root;
TreeNode *temp = NULL;
while(p!=nullptr||!s.empty())
{
while(p)
{
s.push(p);
p=p->left;
}
p=s.top();
if(p->right ==NULL||p->right == temp) //如果p没有右孩子或则其右孩子刚刚被访问过
{
cout<<p->val<<' '; 则访问p节点并将其从栈中删除
s.pop();
temp = p; //标记最近被访问的节点。
p = NULL;
}
else
{
p=p->right;
}
}
}
层序遍历-队列实现:
代码实现
使用c++11编译
采用栈和队列实现
#include<iostream>
using namespace std;
#include<queue>
#include<vector>
#include <stack>
struct TreeNode{
int val;
struct TreeNode * left;
struct TreeNode * right;
TreeNode(int x):
val(x),left(NULL),right(NULL){
}
};
vector<int> censhow(TreeNode * root) //层序
{
vector<int> result;
if(!root) return result;
queue<TreeNode*> q;
q.push(root);
while(q.size())
{
auto t = q.front();
q.pop();
result.push_back(t->val);
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
return result;
}
void print(vector<int> & arr) //层序打印
{
for(vector<int>::iterator it = arr.begin();it != arr.end();it++)
cout<<*it<<" ";
cout<<endl;
}
void PreShow1(TreeNode* root) //先序递归
{
if(!root) return;
cout<<root->val<<' ';
if(root->left)
PreShow1(root->left);
if(root->right)
PreShow1(root->right);
}
void PreShow2(TreeNode* root) //先序栈
{
if(!root) return;
stack<TreeNode*> s;
TreeNode *p = root;
while (p != nullptr|| !s.empty())
{
while(p)
{
cout<<p->val<<' ';
s.push(p);
p = p->left;
}
p = s.top()->right;
s.pop();
}
}
void InShow1(TreeNode*root) //中序递归
{
if(!root) return;
if(root->left)
InShow1(root->left);
cout<<root->val<<' ';
if(root->right)
InShow1(root->right);
}
void InShow2(TreeNode*root) //中序栈
{
if(!root) return;
stack<TreeNode*> s;
TreeNode *p = root;
while(p!=nullptr || !s.empty())
{
while(p)
{
s.push(p);
p=p->left;
}
p=s.top();
cout<<p->val<<' ';
s.pop();
p=p->right;
}
}
void PostShow1(TreeNode*root) //后序递归
{
if(!root) return;
if(root->left) PostShow1(root->left);
if(root->right) PostShow1(root->right);
cout<<root->val<<' ';
}
void PostShow2(TreeNode*root) //后序栈
{
if(!root) return;
stack<TreeNode*> s;
TreeNode *p = root;
TreeNode *temp = NULL;
while(p!=nullptr||!s.empty())
{
while(p)
{
s.push(p);
p=p->left;
}
p=s.top();
if(p->right ==NULL||p->right == temp)
{
cout<<p->val<<' ';
s.pop();
temp = p;
p = NULL;
}
else
{
p=p->right;
}
}
}
int main()
{
TreeNode* l1 = new TreeNode(1);
TreeNode* l2 = new TreeNode(2);
TreeNode* l3 = new TreeNode(3);
TreeNode* l4 = new TreeNode(4);
TreeNode* l5 = new TreeNode(5);
TreeNode* l6 = new TreeNode(6);
TreeNode* l7 = new TreeNode(7);
l1->left = l2;
l1->right = l3;
l2->left = l4;
l2->right = l5;
l3->left = l6;
l3->right = l7;
vector<int> a = censhow(l1);
cout<<"层序遍历:"<<endl;
print(a);
cout<<"先序递归:"<<endl;
PreShow1(l1);
cout<<"\n";
cout<<"先序栈:"<<endl;
PreShow2(l1);
cout<<"\n";
cout<<"中序递归:"<<endl;
InShow1(l1);
cout<<"\n";
cout<<"中序栈:"<<endl;
InShow2(l1);
cout<<"\n";
cout<<"后序递归:"<<endl;
PostShow1(l1);
cout<<"\n";
cout<<"后序栈"<<endl;
PostShow2(l1);
cout<<"\n";
}
运行结果: