数据结构 ----二叉树相关操作(3)

1.二叉树求镜像

什么是二叉树的镜像?
这里写图片描述
如上,右边就是左边这棵树的镜像;
由上图可以看出,求一颗树的镜像就是将二叉树的左右子树交换即可;
这里用递归和非递归两种方法进行求解:
递归实现:

 void TreeMirror(TreeNode* root){
     if(root == NULL){                              
         return;
     }
     //访问动作就是交换左右子树
     Swap(&root->lchild,&root->rchild);
     TreeMirror(root->lchild);
     TreeMirror(root->rchild);
 }

非递归实现:

 void TreeMirrorByLoop(TreeNode* root){
     if(root == NULL){
         return;
     }
     SeqQueue q;
     SeqQueueInit(&q);
     SeqQueuePush(&q,root);
     TreeNode* front = NULL;
     while(SeqQueueFront(&q,&front)){
         Swap(&front->lchild,&front->rchild);
         SeqQueuePop(&q);
         if(front->lchild != NULL){
             SeqQueuePush(&q,front->lchild);
         }
         if(front->rchild != NULL){
             SeqQueuePush(&q,front->rchild);                                                 
        }
     }
     return;
  }
2.判断一颗树是否是完全二叉树;

首先,有如下几种树均是完全二叉树:
这里写图片描述
由以上情况,我们可以对完全对完全二叉树有以下解释:
首先这里使用层序遍历的方法,进行遍历,遍历的过程分为两个阶段:
阶段一:任何一个结点同时具有左右子树(上图中情况1),一旦发现某个结点不是同时具备,又分为三种情况
a)当前结点只有右子树,一定不是完全二叉树;
b)如果当前结点只有左子树,进入第二阶段;
c)如果当前结点没有子树,也进入第二阶段;
阶段二:任何一个结点都必须没有子树.

当遍历结束之后,所有的条件都满足,说明这个树就是完全二叉树,否则,就不是.
代码实现如下:

 int IsCompleteTree(TreeNode* root){
     if(root == NULL){
         return 0;
     }
     SeqQueue q;
     SeqQueueInit(&q);                                                                       
     SeqQueuePush(&q,root);
     //这个变量表示是否要进入第二阶段
     int if_start_step_two_flag = 0;
     TreeNode* cur = NULL;
     while(SeqQueueFront(&q,&cur)){
         SeqQueuePop(&q);
         if(if_start_step_two_flag == 0){
             //阶段一
             if(cur->lchild != NULL && cur->rchild != NULL){
                 //同时具备左右子树
                 SeqQueuePush(&q,cur->lchild);
                 SeqQueuePush(&q,cur->rchild);
             }else if(cur->rchild != NULL && cur->lchild == NULL){
                 //不是完全二叉树
                 return 0;
             }else if(cur->rchild == NULL && cur->lchild != NULL){
                 //当前节点只有左子树没有右子树,进入第二阶段
                 if_start_step_two_flag = 1;
                 SeqQueuePush(&q,cur->lchild);
             }else {
                 //没有左右子树
                 if_start_step_two_flag = 1;
             }
         }else {
             //阶段二
             if(cur->lchild == NULL && cur->rchild ==NULL){
                 ;                                                                           
             }else{
                 return 0;
             }
         }//end阶段一和阶段二的判定
     }//循环结束
     //所有节点都判定完了,此时又没有return 0,此时一定是完全二叉树
     return 1;
 }
3.根据先序和中序遍历的结果重建这棵树;

首先,先序遍历的第一个结点肯定是根结点,然后拿这个结点在中序遍历中找相应的位置,它的左右两边的结点即是它的左右子树,依次这样取下一个先序遍历的结点,再去找中序遍历中相对应的位置,循环;
具体代码实现如下:


 TreeNode* _TreeRebuild(TreeNodeType pre_order[],size_t pre_order_size,size_t* pre_order_inde
                        TreeNodeType in_order[],size_t in_order_left,size_t in_order_right){
     if(in_order_left >= in_order_right){
         //无效区间,当前子树中序遍历结果为空,此时说明这棵子树是空树
         return NULL;
     }
     if(pre_order_index == NULL || *pre_order_index >= pre_order_size){
         //pre_order_index == NULL非法输入
         //*pre_order_index >= pre_order_size 遍历完了
         return NULL;
     }
     //根据先序遍历结果取出当前值,基于这个值构建一个节点
     //new_node 相当于当前子树的根结点
     TreeNode* new_node = CreateTreeNode(pre_order[*pre_order_index]);
     //查找一下当前节点在中序遍历中的位置
     size_t cur_root_in_order_index = Find(in_order,in_order_left,in_order_right,new_node->data);
     //assert(cur_root_in_order_index != (size_t)-1);
     ++(*pre_order_index);
     //左子树区间[in_order_left,cur_root_in_order_index)
     new_node->lchild = _TreeRebuild(pre_order,pre_order_size,pre_order_index,in_order,in_order_left,cur_root_in_order_index);
     //右子树区间[cur_root_in_order_index+1,in_order_right)
     new_node->rchild = _TreeRebuild(pre_order,pre_order_size,pre_order_index,in_order,cur_root_in_order_index+1,in_order_right);
     return new_node;
 }

 TreeNode* TreeRebuild(TreeNodeType pre_order[],TreeNodeType in_order[],size_t size){
     size_t pre_order_index = 0;
     size_t in_order_right = size;
     //[in_order_left,in_order_right)
     return _TreeRebuild(pre_order,size,&pre_order_index,in_order,in_order_left,in_order_right);
 }

 size_t Find(TreeNodeType arry[],size_t left,size_t right,TreeNodeType to_find){
     size_t i = left;
     for(;i<right;i++){
         if(arry[i] == to_find){
             return i;
         }
     }
     return (size_t)-1;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值