Construct the tree traversal and determination

Tree is an important data structure, will be used in many cases, to build today to share tree traversal and judgment, the main achievement are:

  • The binary tree constructed and sequence preorder
  • The constructed binary sequence and subsequent
  • Preorder traversal non-recursive
  • In order non-recursive traversal
  • After the non-recursive traversal sequence
  • Level non-recursive traversal
  • Determine whether the binary tree is a complete binary tree
  • Determine whether a binary tree is a full binary tree
  • Determining whether binary tree is a balanced binary tree
    idea related annotated in the code, as follows:
# include <iostream>
using namespace std;
#include <cstdlib>   
#include <stack>  
#include <queue>
typedef struct Node
{
 char data;
 struct Node *lchild,*rchild;
}*BiTree,BiTreeNode;
//1.先序和中序创建树
BiTree PreInOrder(char preord[],char inord[],int i,int j,int k,int h)
{//先序从i,j,中序从k,h
 BiTree t;
 int m;
 t=(BiTreeNode*)malloc(sizeof(BiTreeNode));
 t->data=preord[i];//得到先序的根节点
 m=k;
 while(inord[m]!=preord[i])m++;//在中序序列中定位根节点
 //递归调用建立左子树
 if(m==k)//表示只有一个节点
  t->lchild=NULL;
 else
  t->lchild=PreInOrder(preord,inord,i+1,i+m-k,k,m-1);
 //递归调用建立右子树
 if(m==h)
  t->rchild=NULL;
 else
  t->rchild=PreInOrder(preord,inord,i+m-k+1,j,m+1,h);
 return t;
}
//2.中序和后序
BiTree BehInOrder(char behord[],char inord[],int i,int j,int k,int h)
{//先序从i,j,中序从k,h
 BiTree t;
 int m;
 t=(BiTreeNode*)malloc(sizeof(BiTreeNode));
 t->data=behord[j];//得到后序的根节点
 m=k;
 while(inord[m]!=behord[j])m++;//在中序序列中定位根节点
 //递归调用建立左子树
 if(m==k)//表示只有一个节点
  t->lchild=NULL;
 else
  t->lchild=BehInOrder(behord,inord,i,i+m-(k+1),k,m-1);
 //递归调用建立右子树
 if(m==h)
  t->rchild=NULL;
 else
  t->rchild=BehInOrder(behord,inord,i+m-k,j-1,m+1,h);
 return t;
}
BiTree CreateBiTree(char preord[],char inord[],int n)
{
 BiTree root;
 if(n<=0)
  root=NULL;
 else
  //前+中root=PreInOrder(preord,inord,0,n-1,0,n-1);
  //后+中
  root=BehInOrder(preord,inord,0,n-1,0,n-1);
 return root;
}
//3.非递归前序遍历(先输出,再进栈,遍历左子树完了到右边)
void Prorder(BiTree bt)
{
 stack<BiTree>s;
 BiTree p=bt;
 while(p!=NULL||!s.empty())
 {
  if(p)
  {
   cout<<p->data<<" ";
   s.push(p);
   p=p->lchild;
  }
  else
  {
   p=s.top();
   s.pop();
   p=p->rchild;
  }
 }
 cout<<endl;
}
//4.非递归中序遍历(栈实现,先进栈,遍历左子树,出栈时输出节点值,再遍历右子树,出栈输出)
void Inorder(BiTree bt)
{
 stack<BiTree>s;
 BiTree p=bt;
 while(p!=NULL||!s.empty())
 {
  if(p)
  {
   s.push(p);
   p=p->lchild;
  }
  else
  {
   p=s.top();
   s.pop();
   cout<<p->data<<" ";
   p=p->rchild;
  }
 }
 cout<<endl;
}
//5.非递归后序遍历(入栈带着标志,当节点标志为1,且没有孩子输出他)
void Beorder(BiTree bt)
{
 stack<pair<BiTree,bool>> s;//栈里面放了一个二元结构体(利用pair),后面的是一个标志
 BiTree p=bt;
 while(p!=NULL||!s.empty())
 {
  if(p)
  {
   s.push(make_pair(p,false));//make_pair自动生成一个结构
   p=p->lchild;
  }
  else//右子树未访问
  {
   if(s.top().second==false)
   {
    s.top().second=true;
    p=s.top().first->rchild;
   }
   else//右子树已访问
   {
    cout<<s.top().first->data<<" ";
    s.pop();
   }
  }
 }
 cout<<endl;
}
//6.非递归层次遍历(利用队列实现1.非空二叉树的根节点指针入队列2.队头元素出队,并输出,将该节点的左右孩子入队)
void LevelOrder(BiTree bt)
{
 queue<BiTree> q;
 BiTree p=NULL;
 if(bt==NULL)
  return;
 q.push(bt);
 while(!q.empty())
 {
  p=q.front();//p保存了q的队头元素,每次进行输出
  q.pop();
  cout<<p->data<<" ";
  if(p->lchild)
   q.push(p->lchild);//左孩子入队
  if(p->rchild)
   q.push(p->rchild);
 }
 cout<<endl;
}
//7.判断是否是满二叉树(用层次遍历做,每个节点都要左右孩子或者为叶节点)
bool IsFullBiTree(BiTree bt)
{
 if(bt==NULL)
  return false;
 queue<BiTree>q;
 BiTree p=NULL;
 q.push(bt);
 bool result=true;
 while(!q.empty())
 {
  p=q.front();
  q.pop();
  if(p->lchild!=NULL&&p->rchild!=NULL)
  {
   q.push(p->lchild);
   q.push(p->rchild);
  }
  else if(p->lchild==NULL&&p->rchild==NULL)
  {
   result=true;
  }
  else
  {
   result=false;
   break;
  }
 }
 return result;
}
//8.判断是否是完全二叉树(用层次遍历做1.可以只有左节点2.这个节点的双亲没有右节点,它不能有左右孩子)
bool IsCompleteBiTree(BiTree bt)
{
 if(bt==NULL)
  return false;
 queue<BiTree>q;
 BiTree p=NULL;
 q.push(bt);
 bool ifchild=false;
 bool result=true;
 while(!q.empty())
 {
  p=q.front();
  q.pop();
  if(ifchild)//双亲没有右孩子只有左孩子,则这个节点不能有孩子
  {
   if(p->lchild!=NULL||p->rchild!=NULL)
   {
    result=false;
    break;
   }
  }
  else
  {
   if(p->lchild!=NULL&&p->rchild!=NULL)
   {
    q.push(p->lchild);
    q.push(p->rchild);
   }
   else if(p->lchild!=NULL&&p->rchild==NULL)
   {
    ifchild=true;
    q.push(p->lchild);
   }
   else if(p->lchild==NULL&&p->rchild!=NULL)
   {
    result=false;
    break;
   }
   else
   {
    ifchild=true;
   }
   }
 }
 return result;
}
//9.判断是否是平衡二叉树(用到了求树深度的函数,左子树为平衡树,右子树为平衡树,左右子树的高度相差不为1)
//(1)时间复杂度高,节点被重复访问
int TreeDepth(BiTree bt)//求深度的函数
{
 if(bt==NULL)
 {
  return 0;
 }
 int left=TreeDepth(bt->lchild);
 int right=TreeDepth(bt->rchild);
 return (left>right)?(left+1):(right+1);
}
bool IsBlanced(BiTree bt)
{
 if(bt==NULL)
 {
  return true;
 }
 int left=TreeDepth(bt->lchild);
 int right=TreeDepth(bt->rchild);
 int diff=left-right;
 if(diff>1||diff<-1)
 {
  return false;
 }
 return IsBlanced(bt->lchild)&&IsBlanced(bt->rchild);
}
//(2)在每次遍历的时候就求出节点的深度,这样避免了重复访问节点
bool IsBalanced2(BiTree bt,int *depth)
{
 if(bt==NULL)
 {
  *depth=0;
  return true;
 }
 int left,right;
 if(IsBalanced2(bt->lchild,&left)&&IsBalanced2(bt->rchild,&right))//左子树和右子树都是平衡树
 {
  int diff=left-right;
  if(diff<=1&&diff>=-1)
  {
   *depth=1+(left>right?left:right);
   return true;
  }
 }
 return false;
}
int main()
{
 //char str1[40]={"ABCDEFG"};//前
 //char str2[40]={"CBDAEGF"};//中
 //char str3[40]={"CDBGFEA"};//后
 /*char str1[40]={"1248950367"};//前
 char str2[40]={"8492051637"};//中
 char str3[40]={"8940526731"};//后*/
 char str1[40]={"1243"};//前
 char str2[40]={"4213"};//中
 char str3[40]={"4231"};//后
 int n=strlen(str1);
 BiTree root;
 root=CreateBiTree(str3,str2,n);
 cout<<"前序:"<<str1<<endl;
 cout<<"中序:"<<str2<<endl;
 cout<<"后序:"<<str3<<endl;
 cout<<"层次遍历输出"<<endl;
 LevelOrder(root);
 cout<<"前序遍历输出"<<endl;
 Prorder(root);
 cout<<"中序遍历输出"<<endl;
 Inorder(root);
 cout<<"后序遍历输出"<<endl;
 Beorder(root);
 if(IsCompleteBiTree(root))
 {
  cout<<"是完全二叉树"<<endl;
 }
 else
  cout<<"不是完全二叉树"<<endl;
 if(IsFullBiTree(root))
 {
  cout<<"是满二叉树"<<endl;
 }
 else
  cout<<"不是满二叉树"<<endl;
 if(IsBlanced(root))
 {
  cout<<"是平衡二叉树"<<endl;
 }
 else
  cout<<"不是平衡二叉树"<<endl;
 int depth=0;
 if(IsBalanced2(root,&depth))
 {
  cout<<"是平衡二叉树,深度为:"<<depth<<endl;
 }
 else
  cout<<"不是平衡二叉树,深度为:"<<depth<<endl;
}

Screenshot operating results:
Here Insert Picture Description
rookie one, if wrong, to welcome the god pointed Oh! Come on!

Published 54 original articles · won praise 8 · views 5319

Guess you like

Origin blog.csdn.net/qq_43411555/article/details/103090935