建立一颗二叉树(不要用数组),求二叉树的前序遍历序列,中序遍历序列,后序遍历序列,层序遍历序列,输出叶子数,和树的高度(根节点为第1层),实现二叉树查找
程序以下图为例:
输出样例:
preorder:
1 2 4 5 8 9 3 6 7
1 2 4 5 8 9 3 6 7
inorder:
4 2 8 5 9 1 6 3 7
4 2 8 5 9 1 6 3 7
postorder:
4 8 9 5 2 6 7 3 1
4 8 9 5 2 6 7 3 1
levelorder:
1 2 3 4 5 6 7 8 9
leavescount:
5
height:
4
8 is found
递归算法都挺好理解关键讲讲非递归遍历算法
前序和中序的非递归算法其实就是按照这个图走迷宫,经过非叶节点3次(只记录前两次),叶节点两次,前序遍历是第一次碰到就把节点输出出来,中序是第二次碰到再输出出来,怎么控制碰到的次数呢?用栈来控制,入栈表示当前第一次经过这个的节点,出栈,表示第二次经过这个节点。
而后序的非递归就有点麻烦了,它的入口和出口与前序中序的是反的,路径不变,如果第一次遇到就打印的的话打印出来的序列正好是后序的逆序,所以第一次遇到时可以先把它存在另一个栈里,最后再全部出栈即可得到正确的后序序列
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
typedef struct btnode* pt;
queue<pt> q;
stack <pt> s,st;
int flag=0;
struct btnode
{
int data;
pt left,right;
};
pt init(int data)//初始化
{
pt tmp=new(struct btnode);
tmp->data=data;
tmp->left=tmp->right=NULL;
return tmp;
}
pt maketree()//笨笨的建树方法,可以通过递归或数组建树,这里只是为了举例子
{
pt root=init(1);
pt tmp1=init(2);
root->left=tmp1;
pt tmp2=init(3);
root->right=tmp2;
pt tmp3=init(4);
tmp1->left=tmp3;
pt tmp4=init(5);
tmp1->right=tmp4;
pt tmp5=init(6);
tmp2->left=tmp5;
pt tmp6=init(7);
tmp2->right=tmp6;
pt tmp7=init(8);
tmp4->left=tmp7;
pt tmp8=init(9);
tmp4->right=tmp8;
return root;
}
void preorder(pt p)//先序的递归算法
{
if(p)
{
cout<<p->data<<" ";
preorder(p->left);
preorder(p->right);
}
}
void preorder2(pt p)//前序非递归算法
{
if(p)
{
pt tmp;
tmp=p;
while(!s.empty()||tmp)//注意两个条件
{
while(tmp)//控制回溯
{
s.push(tmp);//第一次遇到
cout<<tmp->data<<" ";//第一次遇到直接打印
tmp=tmp->left;//按路径继续向左走 ,左孩子为空时回溯
}
if(!s.empty())//控制回溯
{
tmp=s.top();
s.pop();//第二次遇到
tmp=tmp->right;//按路径向右走,右孩子为空时回溯
}
}
}
}
void inorder(pt p)//中序递归算法
{
if(p)
{
inorder(p->left);
cout<<p->data<<" ";
inorder(p->right);
}
}
void inorder2(pt p)//中序非递归算法
{
if(p)
{
pt tmp;
tmp=p;
while(!s.empty()||tmp)
{
while(tmp)
{
s.push(tmp);
tmp=tmp->left;
}
if(!s.empty())
{
tmp=s.top();
s.pop();
cout<<tmp->data<<" ";//第二遇到打印
tmp=tmp->right;
}
}
}
}
void postorder(pt p)//后续递归算法
{
if(p)
{
postorder(p->left);
postorder(p->right);
cout<<p->data<<" ";
}
}
void postorder2(pt p)//后序非递归算法
{
if(p)
{
pt tmp;
tmp=p;
while(!s.empty()||tmp)
{
while(tmp)
{
s.push(tmp);
st.push(tmp);//第一次遇到时放入另一个栈中
tmp=tmp->right;//按路径向右走,右孩子为空时回溯
}
if(!s.empty())
{
tmp=s.top();
s.pop();
tmp=tmp->left;//按路径继续向左走 ,左孩子为空时回溯
}
}
while(!st.empty())//打印后序序列
{
tmp=st.top();
st.pop();
cout<<tmp->data<<" ";
}
}
}
void levelorder(pt p)//层序遍历
{
q.push(p);
while(!q.empty())
{
pt tmp=q.front();
if(tmp->left)
q.push(tmp->left);
if(tmp->right)
q.push(tmp->right);
cout<<tmp->data<<" ";
q.pop();
}
}
int countleaves(pt root)//数叶子数
{
if(!root)
return 0;
if(!root->left&&!root->right)
return 1;
return countleaves(root->left)+countleaves(root->right);
}
int height(pt root)//求数的高度
{
if(!root)
return 0;
if(!root->right&&!root->left)
return 1;
return (height(root->left)>height(root->right)?height(root->left):height(root->right))+1;
}
void search(pt root,int x)//搜索点是否存在
{
if(root)
{
if(root->data==x)
{
flag=1;
cout<<x<<" is found"<<endl;
}
if(!flag)
{
search(root->left,x);
search(root->right,x);
}
}
}
int main()
{
pt root=maketree();
cout<<"preorder:"<<endl;
preorder(root);
cout<<endl;
preorder2(root);
cout<<endl<<endl;
cout<<"inorder:"<<endl;
inorder(root);
cout<<endl;
inorder2(root);
cout<<endl<<endl;
cout<<"postorder:"<<endl;
postorder(root);
cout<<endl;
postorder2(root);
cout<<endl<<endl;
cout<<"levelorder:"<<endl;
levelorder(root);
cout<<endl<<endl;
cout<<"leavescount:"<<endl;
cout<<countleaves(root)<<endl<<endl;
cout<<"height:"<<endl;
cout<<height(root)<<endl<<endl;
flag=0;
search(root,8);
cout<<endl;
return 0;
}
前序和后序遍历非递归的另一个版本,不再讲解,有兴趣的朋友可以看一下
void preorder3(pt p)//先序遍历
{
if(p)
{
pt tmp;
s.push(p);
while(!s.empty())
{
tmp=s.top();
cout<<tmp->data<<" ";
s.pop();
if(tmp->right)
s.push(tmp->right);
if(tmp->left)
s.push(tmp->left);
}
}
}
void postorder3(pt p)//后序遍历
{
pt tmp;
s.push(p);
while(!s.empty())
{
tmp=s.top();
s.pop();
st.push(tmp);
if(tmp->left)
s.push(tmp->left);
if(tmp->right)
s.push(tmp->right);
}
while(!st.empty())
{
tmp=st.top();
st.pop();
cout<<tmp->data<<" ";
}
}