树(二叉树)的基本操作

一、树的基本术语:                                      

结点的度:结点拥有的子树数
树的度:树内各结点的度的最大值
叶子:度为0的结点
分支结点:度不为0的结点
深度:树中结点的最大层次

二、二叉树                                                    

在讨论一般树之前,我们讨论二叉树:1)每个结点最多只有两棵子树;2)二叉树的子树有左右之分
1、二叉树的基本性质
        。。。。。
2、二叉树的存储结构
     顺序存储结构仅适用于完全二叉树,所以一般使用链式存储结构(二叉链表、三叉链表);
     二叉树的二叉链表存储表示
           
typedef  struct  BiTNode{
        TElemType data;
        struct  BitNode *lchild,*rchild;
}BiTNode,*BiTree;


三、二叉树的基本操作                                

#include  <iostream>
#include  <cstdio>
#include  <cstring>
#include  <cstdlib>

using  namespace  std;

typedef  struct  BiTNode
{      
         char  data;
         struct  BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
int  Max( int  x, int  y)
{
         return  x>y?x:y;
}

void  Create(BiTree &T)   // 先序建一颗二叉树
{
        char  ch;
       scanf(  "%c" ,&ch);
        if (ch== '#'  )
              T=NULL;
        else
       {
              T=(BiTNode *)malloc(  sizeof (BiTNode));
              T->data=ch;
              Create(T->lchild);
              Create(T->rchild);
       }
}
void  Preorder(BiTree &root)   // 先序遍历打印二叉树
{
         if (root!=NULL)
       {
              printf(  "%c " ,root->data);
              Preorder(root->lchild);
              Preorder(root->rchild);
       }
}
void  Inorder(BiTree &root)   // 中序遍历打印二叉树
{
         if (root!=NULL)
       {
              Inorder(root->lchild);
              printf(  "%c " ,root->data);
              Inorder(root->rchild);
       }
}
void  Postorder(BiTree &root)   // 后续遍历打印二叉树
{
         if (root!=NULL)
       {
              Postorder(root->lchild);
              Postorder(root->rchild);
              printf(  "%c " ,root->data);
       }
}
void  Preorderleaf(BiTree &root)  // 先序遍历输出叶子节点
{
         if (root!=NULL)
       {
               if (root->lchild==NULL&&root->rchild==NULL)
                    printf(  "%c " ,root->data);
              Preorderleaf(root->lchild);
              Preorderleaf(root->rchild);
       }
}
int  LeafCount(BiTree &root)   // 统计叶子节点的个数
{
         int  leaf;
         if (root==NULL)
            leaf=0;
         else  if  (root->lchild==NULL&&root->rchild==NULL)
            leaf=1;
         else
            leaf=LeafCount(root->lchild)+LeafCount(root->rchild);
         return  leaf;
}
int  PostTreeDepth(BiTree &root)   // 统计树的高度
{
      int  hl,hr,max;
     if (root!=NULL)
    {
          hl=PostTreeDepth(root->lchild);
          hr=PostTreeDepth(root->rchild);
          max=Max(hl,hr);
           return  max+1;
    }
     else
         return  0;
}
void  dowork()
{
       BiTree cam;
       Create(cam);
       Preorder(cam);  // 先序遍历
       printf(  "\n" );
       Inorder(cam);  // 中序遍历
       printf(  "\n" );
       Postorder(cam);  // 后续遍历
       printf(  "\n" );
       
       printf(  " 叶子节点: " );
       Preorderleaf(cam);
       printf(  "\n" );
       
       printf(  " 叶子节点的个数为 :%d\n" ,LeafCount(cam));
       printf(  " 树的深度为 :%d\n" ,PostTreeDepth(cam));
}
int  main()
{
       dowork();
         return  0;
}


下面的代码是可以运行的,在《零基础学算法》中有,直接拷贝过来。
main.cpp中

  #include <stdio.h> 
  #include "3-1 BinTree.c"
   
  void oper(ChainBinTree *p) //操作二叉树结点数据 
  {
        printf("%c ",p->data); //输出数据
        return;
  }
  ChainBinTree *InitRoot()  //初始化二叉树的根 
  {
      ChainBinTree *node;
      if(node=(ChainBinTree *)malloc(sizeof(ChainBinTree))) //分配内存
      {
          printf("\n输入根结点数据:");
          scanf("%s",&node->data);
          node->left=NULL;
          node->right=NULL;
          return BinTreeInit(node);
      }
      return NULL;
  }
  void AddNode(ChainBinTree *bt)  //添加结点
  {
       ChainBinTree *node,*parent;
       DATA data;
       char select;
      if(node=(ChainBinTree *)malloc(sizeof(ChainBinTree))) //分配内存
      {
          printf("\n输入二叉树结点数据:");
          fflush(stdin);//清空输入缓冲区 
          scanf("%s",&node->data);
          node->left=NULL; //设置左右子树为空 
          node->right=NULL;
          
  
          printf("输入父结点数据:");
          fflush(stdin);//清空输入缓冲区 
          scanf("%s",&data);
          parent=BinTreeFind(bt,data);//查找指定数据的结点 
          if(!parent)//若未找到指定数据的结点 
          {
              printf("未找到父结点!\n");
              free(node); //释放创建的结点内存 
              return;
           }
           printf("1.添加到左子树\n2.添加到右子树\n");
           do{
              select=getch();
              select-='0';
              if(select==1 || select==2)
                  BinTreeAddNode(parent,node,select); //添加结点到二叉树 
           }while(select!=1 && select!=2);
      }
      return ;
  }
  int main() 
  {
      ChainBinTree *root=NULL; //root为指向二叉树根结点的指针 
      char select;
      void (*oper1)(); //指向函数的指针 
      oper1=oper; //指向具体操作的函数 
      do{
          printf("\n1.设置二叉树根元素    2.添加二叉树结点\n");
          printf("3.先序遍历            4.中序遍历\n");
          printf("5.后序遍历            6.按层遍历\n");
          printf("7.二叉树深度          0.退出\n");
          select=getch();
          switch(select){
          case '1': //设置根元素 
               root=InitRoot();
               break;
          case '2': //添加结点 
               AddNode(root);
               break;
          case '3'://先序遍历
               printf("\n先序遍历的结果:");
               BinTree_DLR(root,oper1);
               printf("\n");
               break;
          case '4'://中序遍历 
               printf("\n中序遍历的结果:");
               BinTree_LDR(root,oper1);
               printf("\n");
               break;
          case '5'://后序遍历 
               printf("\n后序遍历的结果:");
               BinTree_LRD(root,oper1);
               printf("\n");
               break;
          case '6'://按层遍历
               printf("\n按层遍历的结果:");
               BinTree_Level(root,oper1);
               printf("\n");
               break;
          case '7'://二叉树的深度
              printf("\n二叉树深度为:%d\n",BinTreeDepth(root));
              break; 
          case '0':
               break;
         }
     }while(select!='0');
     BinTreeClear(root);//清空二叉树 
     root=NULL;
     getch();
     return 0;
 }


3-1BinTree.cpp中

 #include <stdio.h> 
 #include <stdlib.h> 
   
 #define QUEUE_MAXSIZE 50
 typedef char DATA;       //定义元素类型 
 typedef struct ChainTree  //定义二叉树结点类型 
 {
       DATA data;    //元素数据
       struct ChainTree *left;    //左子树结点指针
      struct ChainTree *right;    //右子树结点指针
 }ChainBinTree;
  
 ChainBinTree *BinTreeInit(ChainBinTree *node) //初始化二叉树根结点 
 {
       if(node!=NULL) //若二叉树根结点不为空 
           return node;
       else
           return NULL;
 }
 int BinTreeAddNode(ChainBinTree *bt,ChainBinTree *node,int n) //添加数据到二叉树 
  //bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树 
 {
      if(bt==NULL)
      {
          printf("父结点不存在,请先设置父结点!\n");
          return 0;
      } 
      switch(n)
      {
          case 1: //添加到左结点 
              if(bt->left) //左子树不为空 
              {
                  printf("左子树结点不为空!\n");
                  return 0;
              }else
                  bt->left=node;
              break;
          case 2://添加到右结点
              if( bt->right) //右子树不为空 
              {
                  printf("右子树结点不为空!\n"); 
                  return 0;
              }else
                  bt->right=node;
              break;
          default:
              printf("参数错误!\n");
              return 0;
      }
      return 1;
 }
 ChainBinTree *BinTreeLeft(ChainBinTree *bt) //返回左子结点 
 {
      if(bt)
          return bt->left;
      else
          return NULL;
 }
 ChainBinTree *BinTreeRight(ChainBinTree *bt) //返回右子结点 
 {
      if(bt)
          return bt->right;
      else
          return NULL;
 }
 int BinTreeIsEmpty(ChainBinTree *bt) //检查二叉树是否为空,为空则返回1,否则返回0 
 {
      if(bt)
          return 0;
      else
          return 1;
 } 
 int BinTreeDepth(ChainBinTree *bt) //求二叉树深度
 {
      int dep1,dep2;
      if(bt==NULL)
          return 0; //对于空树,深度为0
      else
      {
          dep1 = BinTreeDepth(bt->left); //左子树深度 (递归调用)
          dep2 = BinTreeDepth(bt->right); //右子树深度 (递归调用)
          if(dep1>dep2)
             return dep1 + 1; 
          else
              return dep2 + 1; 
      } 
 } 
 ChainBinTree *BinTreeFind(ChainBinTree *bt,DATA data) //在二叉树中查找值为data的结点 
 {
      ChainBinTree *p;
      if(bt==NULL)
          return NULL;
      else
      {
          if(bt->data==data)
              return bt; 
          else{ // 分别向左右子树递归查找 
              if(p=BinTreeFind(bt->left,data))
                  return p;
             else if(p=BinTreeFind(bt->right, data)) 
                 return p;
             else
                 return NULL; 
         } 
     } 
 } 
 void BinTreeClear(ChainBinTree *bt) // 清空二叉树,使之变为一棵空树
 {
      if(bt)
      {
          BinTreeClear(bt->left); //清空左子树 
          BinTreeClear(bt->right);//清空右子树 
          free(bt);//释放当前结点所占内存 
          bt=NULL;
      }
      return; 
 }
 void BinTree_DLR(ChainBinTree *bt,void (*oper)(ChainBinTree *p))  //先序遍历 
 {     
      if(bt)//树不为空,则执行如下操作 
      {
          oper(bt); //处理结点的数据 
          BinTree_DLR(bt->left,oper);
          BinTree_DLR(bt->right,oper);
      }
      return; 
 } 
 void BinTree_LDR(ChainBinTree *bt,void(*oper)(ChainBinTree *p))  //中序遍历 
 {
      if(bt)//树不为空,则执行如下操作 
      {
          BinTree_LDR(bt->left,oper); //中序遍历左子树
          oper(bt);//处理结点数据 
          BinTree_LDR(bt->right,oper); //中序遍历右子树/
      }
      return; 
 } 
 void BinTree_LRD(ChainBinTree *bt,void (*oper)(ChainBinTree *p)) //后序遍历
 {
      if(bt)
      {
          BinTree_LRD(bt->left,oper); //后序遍历左子树 
          BinTree_LRD(bt->right,oper); //后序遍历右子树/
          oper(bt); //处理结点数据
      }
      return; 
 }
 
 void oper(ChainBinTree *p) //操作二叉树结点数据 
 {
      printf("%c ",p->data); //输出数据
      return;
 }
 
 void BinTree_Level(ChainBinTree *bt,void (*oper)(ChainBinTree *p)) //按层遍历 
 {
      ChainBinTree *p;
      ChainBinTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈 
      int head=0,tail=0;//队首、队尾序号 
      if(bt)//若队首指针不为空     
      {
          tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列队尾序号 
          q[tail] = bt;//将二叉树根指针进队
      }
      while(head!=tail) //队列不为空,进行循环 
      {
          head=(head+1)%QUEUE_MAXSIZE; //计算循环队列的队首序号 
          p=q[head]; //获取队首元素 
          oper(p);//处理队首元素 
          if(p->left!=NULL) //若结点存在左子树,则左子树指针进队 
          {
              tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 
              q[tail]=p->left;//将左子树指针进队 
          }
                  
          if(p->right!=NULL)//若结点存在右孩子,则右孩子结点指针进队 
          {
              tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 
              q[tail]=p->right;//将右子树指针进队 
          }
      }
      return; 
 }


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值