建立二叉树的链式存储结构,并对二叉树前序遍历、中序遍历、后序遍历以及层序遍历,求二叉树的深度,销毁二叉树。
(1)二叉树的建立
前序建立,即先建立根节点,再建立左子树,最后建立右子树,结点值的输入需要按照先序遍历的方式输入,以-1表示结点为空,例如一个深度为3的二叉树每层分别为1 ,2 3, 4 5 6 7,则应输入1 2 4 -1 -1 5 -1 -1 3 6 -1 -1 7 -1 -1。
BiTreeNode *CreateBiTree()//建立树,输入结点值,输入-1表示结点为空,输入非数字结束
{
int n;
BiTreeNode *T;
if(!(cin>>n))//如果输入非法,则返回NULL
return NULL;
else if(n==-1)//输入-1,表示该结点为空
T=NULL;
else
{
T=new BiTreeNode;//分配内存
T->value=n;
T->lchild=CreateBiTree();
T->rchild=CreateBiTree();
}
return T;
}
(2)二叉树的遍历
基于二叉树的递归定义,可以得到二叉树的递归遍历算法
前序遍历:二叉树为空,空操作。先访问根结点,前序遍历左子树,前序遍历右子树
递归算法
void PreOrderTraverse(BiTreeNode *T)//先序遍历
{
if(T)
{
cout<<T->value<<" ";//
PreOrderTraverse(T->lchild);//
PreOrderTraverse(T->rchild);
}
}
非递归算法
思路:先将根节点入栈,将其左结点依次入栈,一直到左结点为空,然后一层层退栈处理其右子树,对每一次退栈的元素的右结点执行与根节点相同的操作,在每个元素入栈之前输出,即可实现先头结点,再左子树,再右子树的先序遍历
void NPreOrderTraverse(BiTreeNode *T)//非递归先序遍历
{
BiTreeNode *p=T;
stack<BiTreeNode*> nodes;
while(p!=NULL || !nodes.empty())
{
while(p!=NULL)
{
cout<<p->value<<" ";
nodes.push(p);
p=p->lchild;
}
if(!nodes.empty())
{
p=nodes.top();
nodes.pop();
p=p->rchild;
}
}
}
中序遍历:二叉树为空,空操作。中序遍历左子树,访问根结点,中序遍历右子树
void InOrderTraverse(BiTreeNode *T)//中序遍历
{
if(T)
{
InOrderTraverse(T->lchild);//
cout<<T->value<<" ";//
InOrderTraverse(T->rchild);//
}
}
非递归算法:思路与前序遍历相同,但输出是在元素退栈之后,这样才能保证左结点先输出
void NInOrderTraverse(BiTreeNode *T)//非递归中序遍历
{
BiTreeNode *p=T;
stack<BiTreeNode*> nodes;
while(p!=NULL || !nodes.empty())
{
while(p!=NULL)
{
nodes.push(p);
p=p->lchild;
}
if(!nodes.empty())
{
p=nodes.top();
cout<<p->value<<" ";
nodes.pop();
p=p->rchild;
}
}
}
后序遍历:二叉树为空,空操作。后序遍历左子树,后序遍历右子树,访问根结点
void PostOrderTraverse(BiTreeNode *T)//后序遍历
{
if(T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<T->value<<" ";
}
}
非递归算法:根节点需要在最后遍历,因此按照之前前序非递归的思路不能实现后序遍历
思路:对于任一结点,先将其入栈。如果不存在子结点,则可以直接输出,如果存在左孩子或者右孩子,且左孩子和右孩子都已入过栈,也可以直接输出,如果存在左右孩子且没有被访问,则将右孩子和左孩子依次入栈(这个顺序很重要,保证了左孩子比右孩子先出栈,先被处理和访问)
void NPostOrderTraverse(BiTreeNode *T)//非递归后序遍历
{
BiTreeNode *p=T;
BiTreeNode *cur,*pre=NULL;
stack<BiTreeNode*> s;
if(T!=NULL)
s.push(T);
while(!s.empty())
{
cur=s.top();
if((cur->lchild==NULL&&cur->rchild==NULL)||(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
{
cout<<cur->value<<" ";
s.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild);
if(cur->lchild!=NULL)
s.push(cur->lchild);
}
}
}
层序遍历:二叉树为空,空操作。从根结点开始,按层遍历二叉树
思路;从根结点开始,对每层元素,都依次将其左右结点压入序列,记录序列每层结点开始与结束的位置,即可按层遍历。
void LevelOrderTraverse(BiTreeNode *T)//层序遍历
{//若要输出单层结点,只需在第一个while循环中加入变量depth记录层数,只在指定层输出即可
if(T)
{
vector<BiTreeNode*> vec;//存放结点
int cur=0,last=1;
vec.push_back(T);//把第一层压入vec
while(cur<vec.size())//cur进行当前层的遍历
{
last=vec.size();//到当前层为止的所有结点数
while(cur<last)
{//此处的while循环结束后,cur已经遍历完当前层,vec已把当前层结点的左右孩子都压入。
cout<<vec[cur]->value<<" ";
if(vec[cur]->lchild!=NULL)
vec.push_back(vec[cur]->lchild);
if(vec[cur]->rchild!=NULL)
vec.push_back(vec[cur]->rchild);
cur++;
}
}
}
}
(3)求二叉树的深度
若根结点为空,则返回深度为0,否则按照递归的方法,依次求左子树和右子树的深度,返回较大的深度值,加1(因为还要加上该结点的这一层)后返回。递归完毕即可求得深度值。
int TreeDepth(BiTreeNode *root) //求树的最大深度
{
if (root == NULL)
return 0;
int left = TreeDepth(root->lchild);
int right = TreeDepth(root->rchild);
if (left > right)
return left + 1;
else
return right + 1;
}
(4)销毁二叉树
同样按照递归的方式销毁二叉树,释放内存
void DestroyBiTree(BiTreeNode *&T)//销毁一棵树
{
if(T!=NULL)
{
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
delete T;
}
}
完整代码:
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
struct BiTreeNode//树的结构
{
int value;
BiTreeNode *lchild;
BiTreeNode *rchild;
};
struct FlagNode
{
int isfirst;
BiTreeNode *node;
};
BiTreeNode *CreateBiTree()//建立树,输入结点值,输入-1表示结点为空,输入非数字结束
{
int n;
BiTreeNode *T;
if(!(cin>>n))//如果输入非法,则返回NULL
return NULL;
else if(n==-1)//输入-1,表示该结点为空
T=NULL;
else
{
T=new BiTreeNode;//分配内存
T->value=n;
T->lchild=CreateBiTree();
T->rchild=CreateBiTree();
}
return T;
}
void PreOrderTraverse(BiTreeNode *T)//先序遍历
{
if(T)
{
cout<<T->value<<" ";//
PreOrderTraverse(T->lchild);//
PreOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTreeNode *T)//中序遍历
{
if(T)
{
InOrderTraverse(T->lchild);//
cout<<T->value<<" ";//
InOrderTraverse(T->rchild);//
}
}
void PostOrderTraverse(BiTreeNode *T)//后序遍历
{
if(T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<T->value<<" ";
}
}
void NPreOrderTraverse(BiTreeNode *T)//非递归先序遍历
{
BiTreeNode *p=T;
stack<BiTreeNode*> nodes;
while(p!=NULL || !nodes.empty())
{
while(p!=NULL)
{
cout<<p->value<<" ";
nodes.push(p);
p=p->lchild;
}
if(!nodes.empty())
{
p=nodes.top();
nodes.pop();
p=p->rchild;
}
}
}
void NInOrderTraverse(BiTreeNode *T)//非递归中序遍历
{
BiTreeNode *p=T;
stack<BiTreeNode*> nodes;
while(p!=NULL || !nodes.empty())
{
while(p!=NULL)
{
nodes.push(p);
p=p->lchild;
}
if(!nodes.empty())
{
p=nodes.top();
cout<<p->value<<" ";
nodes.pop();
p=p->rchild;
}
}
}
void NPostOrderTraverse(BiTreeNode *T)//非递归后序遍历
{
BiTreeNode *p=T;
BiTreeNode *cur,*pre=NULL;
stack<BiTreeNode*> s;
if(T!=NULL)
s.push(T);
while(!s.empty())
{
cur=s.top();
if((cur->lchild==NULL&&cur->rchild==NULL)||(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
{
cout<<cur->value<<" ";
s.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild);
if(cur->lchild!=NULL)
s.push(cur->lchild);
}
}
}
void LevelOrderTraverse(BiTreeNode *T)//层序遍历
{//若要输出单层结点,只需在第一个while循环中加入变量depth记录层数,只在指定层输出即可
if(T)
{
vector<BiTreeNode*> vec;//存放结点
int cur=0,last=1;
vec.push_back(T);//把第一层压入vec
while(cur<vec.size())//cur进行当前层的遍历
{
last=vec.size();//到当前层为止的所有结点数
while(cur<last)
{//此处的while循环结束后,cur已经遍历完当前层,vec已把当前层结点的左右孩子都压入。
cout<<vec[cur]->value<<" ";
if(vec[cur]->lchild!=NULL)
vec.push_back(vec[cur]->lchild);
if(vec[cur]->rchild!=NULL)
vec.push_back(vec[cur]->rchild);
cur++;
}
}
}
}
int TreeDepth(BiTreeNode *root) //求树的最大深度
{
if (root == NULL)
return 0;
int left = TreeDepth(root->lchild);
int right = TreeDepth(root->rchild);
if (left > right)
return left + 1;
else
return right + 1;
}
void DestroyBiTree(BiTreeNode *&T)//销毁一棵树
{
if(T!=NULL)
{
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
delete T;
}
}
int main()
{
BiTreeNode *pTree;
cout<<"二叉树的前序建立,输入二叉树:"<<endl;
pTree=CreateBiTree();
cout<<"先序遍历"<<endl;
PreOrderTraverse(pTree);
cout<<endl;
cout<<"非递归先序遍历"<<endl;
NPreOrderTraverse(pTree);
cout<<endl;
cout<<"中序遍历"<<endl;
InOrderTraverse(pTree);
cout<<endl;
cout<<"非递归中序遍历"<<endl;
NInOrderTraverse(pTree);
cout<<endl;
cout<<"后序遍历"<<endl;
PostOrderTraverse(pTree);
cout<<endl;
cout<<"非递归后序遍历"<<endl;
NPostOrderTraverse(pTree);
cout<<endl;
cout<<"层序遍历"<<endl;
LevelOrderTraverse(pTree);
cout<<endl;
cout<<"树的深度为"<<endl;
cout<<TreeDepth(pTree)<<endl;
cout<<endl;
DestroyBiTree(pTree);
return 0;
}