二叉树操作--数据结构

二叉树操作:
实现以二叉链表为存储结构的二叉树的创建、遍历、查找、插入和删除操作。
说明:
1、按先序遍历思想创建二叉树;
2、分别实现中序遍历和层次遍历;
3、给定元素值查找结点指针位置并返回其指针,可利用指针引用data域输出;
4、实现插入左右孩子操作,指定元素值,找到结点后若已存在对应位置的孩子结点则不插入;
5、删除指定元素值的结点,若该结点存在子树则将其子树所有结点全部删除回收;

6、程序提供简单功能菜单。 


#include <iostream>


using namespace std;


//定义一个二叉树 
typedef struct node
{
 char date;    //数据成员
 struct node *lchild,*rchild;
} BTNode,*SecondTree;

//定义一个全局变量树
SecondTree seTree;
//定义全局变量,用来判断是否有此亲节点;
bool boolen=false;

//定义一个队,层次遍历时用
typedef struct Queue
{
 char chardate;
 struct Queue *next;

}* LQueue;

//判断队是否为空
bool isEmpaty(LQueue D);
//入队操作
void PushQueue(LQueue D,char pchar);
//出队函数,返回值char类型
char PopQueue(LQueue D);
//通过父节点,返回孩子节点
bool returnSun(SecondTree T,char f,char &sun1,char &sun2);
//层次遍历二叉树
void CengCi(SecondTree T);
//中序遍历二叉树
void MidTree(SecondTree Tree);
//先序遍历二叉树
void PreTree(SecondTree Tree);
//创建二叉树
void CreateBTNode(BTNode *);
//用先序遍历创建二叉树
//系统默认生成的广义表
//查找节点
bool findTree(SecondTree T,char f);
//插入节点
bool TreeInsert(SecondTree &T,char parent,char insert);
//删除节点
bool delNode(SecondTree &T,char delchar);
//主菜单
void Menu();
//导航栏
int MenuMethod();

int main()
{

	MenuMethod();

	return 0;
}

//创建二叉树
void CreateBTNode(BTNode *)
{

 BTNode *&T=seTree;
 cout<<endl<<"程序默认了一个以广义表形式构造的二叉树。无需手动输入。返回主菜单。"<<endl;

 char c[19]="A(B(D(,G)),C(E,F))";
 
 BTNode*St[10],*p;

 int top=-1,k,j=0;
 char ch;

 T=NULL;
 ch=c[j];
 while(ch!='\0')
 {
  switch(ch)
  {
  case '(' :top++;St[top]=p;k=1;break;//开始处理左孩子节点
  case ')' :top--;break;
  case ',' :k=2;break;//开始处理右孩子节点
  default :p=new BTNode;
    p->date =ch;
    p->lchild=p->rchild=NULL;
    if(T==NULL)//尚未建立根节点
    {
     T=p;//*p为根节点
    }
    else
    {
     switch(k)
     {
     case 1:St[top]->lchild=p;break;
     case 2:St[top]->rchild=p;break;
     }
    }
  }
  j++;
  ch=c[j];

 }
}


//查找节点元素  如果T中存在字符f则返回true,并打印出一句话”f 字符已找到!“。否则返回false
bool findTree(SecondTree T,char f)
{
 SecondTree top=T;
 if(T==NULL)
 {
  return false;
 }
 if(T->date!=f)
 {
  findTree(T->lchild, f);
  findTree(T->rchild, f);
 
 }
 else 
 {
  cout<<f<<" 字符已找到!!!!!"<<endl;
  return true;
 }
 
  return false; 
}
/*

插入节点元素,如果找不到要插入节点的双亲则返回false 找到结点后若已存在对应
位置的孩子结点则不插入返回false ,若找到结点后没有字节点 ,则插入节点元素返回true
*/
bool TreeInsert(SecondTree &T,char parent,char insert)
{
 


 //SecondTree top=T;
 BTNode *Jnode;
 if(T==NULL)
 {
  return false;
  cout<<"二叉树为空。"<<endl;
 }
 
 
 else if(T->date==parent ) 
 {
  boolen=true;
  if (T->lchild!=NULL&&T->rchild!=NULL)
  {
   cout<<"左右孩子节点都已经存在。无须再插入。"<<endl;
   return false;
  
  }
  else if (T->lchild==NULL)
  {
    Jnode=new node;
    Jnode->date=insert;
    Jnode->lchild=NULL;
    Jnode->rchild=NULL;
    T->lchild=Jnode;
   
    cout <<"插入左孩子节点成功"<<endl;
    return true;
  }
  else  if(T->rchild==NULL)
  {
    Jnode=new node;
    Jnode->date=insert;
    Jnode->lchild=NULL;
    Jnode->rchild=NULL;
    T->rchild=Jnode;
    
    cout <<"插入右孩子节点成功"<<endl;
    return true;
  }
   
 
 }  
 else if(T->date!=parent)
 {
  TreeInsert(T->lchild,parent,insert);
 
 

  TreeInsert(T->rchild,parent,insert);
  
  
 }
 
 return false; 
}


//定义删除节点函数,第一个参数为指向树的指针,第二个参数为要删除的节点字符
bool delNode(SecondTree &T,char delchar)
{ 
 if (T!=NULL)
 {
 
  //如果跟节点不为空
   if (T->date==delchar)
   {//如果根节点为要删除的节点···
    cout<<"已找到节点!!下面执行删除"<<endl;
    /**/
    delete T->lchild;
    T->lchild=NULL;
    delete T->rchild;
    T->rchild=NULL;
       delete T;
    T=new node;
    T->lchild=NULL;
    T->rchild=NULL;   
    return true;

   }
   else if (T->lchild!=NULL&&T->lchild->date==delchar)
   {
    //如果左孩子为要删除的节点
    cout <<"删除左孩子:"<<endl;
    delete T->lchild->lchild;
    delete T->lchild->rchild;
    delete T->lchild;
    T->lchild=NULL;
    return true;
   
   }
   else if (T->rchild!=NULL&&T->rchild->date==delchar)
   {
    //如果左孩子为要删除的节点
     cout <<"删除右孩子:"<<endl;   

     delete T->rchild->lchild;
     delete T->rchild->rchild;
     delete T->rchild;
     T->rchild=NULL;
     return true;
   }
   else 
   {
    if(T->lchild!=NULL)
    {   
     //如果左孩子不为空
     delNode(T->lchild,delchar);
    }
    if(T->rchild!=NULL)
    { 
     //如果右孩子不为空
     delNode(T->rchild,delchar);
    }
   
   }
 }
 

 return false;

}


//定义目录函数
void Menu(){
	cout<<endl<<"                                二叉树操作"<<endl;
	cout<<endl;
    cout<<"********************************************************************************";
    cout <<endl<<"功能表:    "<<endl<<endl;
	cout <<"        1:  先序遍历创建树;                2:  中序遍历树;"<<endl<<endl;
    cout <<"        3:  先序遍历树;                    4:  层次遍历;"<<endl<<endl;
	cout <<"        5:  插入节点;                      6:  删除节点;"<<endl<<endl;
	cout <<"        7:  查找节点;                      8:  结束操作;"<<endl;
	cout<<endl<<"********************************************************************************"<<endl;

}

int MenuMethod()
{
 char Cnumber;
 //输出目录
 Menu();

 cout <<endl<<"请您按键选择:"<<endl;
 cin >>Cnumber;
 
 while(Cnumber!=0)
 {
  switch(Cnumber)
  {
   
   case '1':
    //先序遍历创建树
    CreateBTNode(seTree);
    break;
   case '2':
    cout<<"中序遍历结果:"<<endl;
    MidTree(seTree);//调用中序遍历
    cout<<"返回主菜单。"<<endl;
    break;
       
   case '3':
    cout<<"先序遍历结果:"<<endl;
             PreTree(seTree);//调用先序遍历  
    cout<<"返回主菜单。"<<endl;
    break;
   
   case '4':
    //层次遍历
    CengCi(seTree); 
     cout<<"返回主菜单。"<<endl;
    break;
      case '5':
     //插入字符
     char parent,insert;
     cout<<"请输入你要插入字符的双亲:"<<endl;
     cin>>parent;
     cout<<"输入你要插入的字符"<<endl;
     cin>>insert;
     TreeInsert(seTree,parent,insert);
     if(boolen==false)
     {
      cout<<"插入失败,不存在此双亲。,返回主菜单。"<<endl;
     }
     break;  
   case '6':
    //删除节点
     char delchar;
     cout <<"请输入你要删除的节点字符:"<<endl;
     cin >>delchar;
    delNode(seTree,delchar);
     cout<<"返回主菜单。"<<endl;
    break;

   case '7':
     //调用查找树的节点函数
    
     char f;
     cout<<"请输入你要查找的字符"<<endl;
     cin>>f; 
     findTree(seTree, f);
     break;
   case '8':
     return 0;
     break;
   default :    
    //如果输入错误
    cout <<"输入错误!!!请重新输入!"<<endl;    
    break; 
  }
  Menu();//输出目录
  cout <<endl<<"请输入你的选择:"<<endl;
     cin >>Cnumber;
 }
 return 0;
}

//判断队是否为空
bool isEmpaty(LQueue D)
{
 if (D->next==NULL)
 {
  return true;
 }
 else 
  return false;
}
//入队操作
void PushQueue(LQueue D,char pchar)
{
 while (D->next!=NULL)
 {
  D=D->next;
 } 
 
 D->next=new Queue;
 D->next->chardate=pchar;
 D->next->next=NULL;

}
//出队函数,返回值char类型
char PopQueue(LQueue D)
{

 char pchar;
 if(D->next!=NULL)
 { 
  pchar=D->next->chardate;
 }
 else 
 {
  pchar='#';
  return pchar;
 }
 if (D->next->next!=NULL)
 {
  D->next=D->next->next;
 }
 else 
 {
  D->next=NULL;
 }
 return pchar;

}

//通过父节点,返回孩子节点
bool returnSun(SecondTree T,char f,char &sun1,char &sun2)
{

 
 SecondTree top=T;
 if(T==NULL)
 {
   return false;
 }
 if(T->date!=f)
 {
  if (T->lchild!=NULL)
  returnSun(T->lchild, f,sun1,sun2);
  if (T->rchild!=NULL)
  returnSun(T->rchild, f,sun1,sun2);
 
 }
 else 
 {
  //cout<<f<<" 字符已找到lelelell!"<<endl;
  if (T->lchild!=NULL)
  {      //如果左孩子不为空,把其值储存到sun1中
    sun1=T->lchild->date;
  }
  else
  {
    sun1='#';
  }
  if (T->rchild!=NULL) 
  {     //如右孩子不为空,把其值储存到sun2中
    sun2=T->rchild->date;
  }
  else
  {
    sun2='#';
  }

  return true;
 }
 
  return false; 
}


//层次遍历二叉树
void CengCi(SecondTree T)
{

 SecondTree Top=T;
 LQueue TopQueue;
 TopQueue=new Queue;
 cout<<endl<<"层次遍历二叉树: "<<endl;
 TopQueue->next=NULL;
 if (T!=NULL)
 {  //如果头结点不为空,读出头结点。
  cout <<T->date<<endl;
  //如果左孩子不为空,入队
  if (T->lchild!=NULL)
  {
   PushQueue(TopQueue,T->lchild->date);
  }
  //如果右孩子不为空,入队
 
  if (T->rchild!=NULL)
  {
   PushQueue(TopQueue,T->rchild->date);
  }
 }
 //while 队不为空,出队 ,读该节点,把孩子入队
 char pchar;
 char sun1,sun2;

 if (!isEmpaty(TopQueue))
 {
  while (!isEmpaty(TopQueue))
  {
   //出队
      pchar=PopQueue(TopQueue);
   //找到pchar 读出它
   cout<<pchar<<endl;
   returnSun(T,pchar,sun1,sun2);//获得出队元素的左右孩子
   if(sun1!='#')
   {//左孩子不为空。则入队   
    PushQueue(TopQueue,sun1); 
   }
   if(sun2!='#')
   {//右孩子不为空。则入队 
    PushQueue(TopQueue,sun2);  
   }   
  }
 }

}

//中序遍历二叉树
void MidTree(SecondTree Tree)
{ 
 SecondTree top=Tree;
 if(top!=NULL)
 {    //如果节点不为空
  
  
  MidTree(top->lchild); //先序遍历左子树
  
  cout<<top->date<<endl;//输出节点数
  MidTree(top->rchild);//先序遍历右子树
  
 }

}

//先序遍历二叉树,参数为指向结构体变量的指针
void PreTree(SecondTree Tree)
{
 
 SecondTree top=Tree;
 if(top!=NULL)
 {    //如果节点不为空
  cout<<top->date<<endl;//输出节点数
  PreTree(top->lchild); //先序遍历左子树 
  PreTree(top->rchild);//先序遍历右子树
 }

}
 


输出结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值