二叉树镜像,根据数组生成一个完全二叉树

额, 先看下什么是完全二叉树 ,
叶子只能出现在最下面的二层
最下层的叶子一定集中在左部的连续位置
倒数第二层 若有叶子结点 一定在右部连续位置
如果结点的度为1 ,则该结点只有左孩子
同样结点的二叉树,完全二叉树的深度最小

这是一个完全二叉树

以下都不是完全二叉树

根据数组生成一个完全二叉树, 


思路1:叶子节点的下标/2 就是对应的父节点,(此思路的核心)
          先有一个数组保存所有的节点,
          然后生成每一个节点,然后根据生成节点的下标/2 找到父节点,
          如果下标是偶数, 那就是左孩子,下标为奇数,是右孩子.

思路2:数组的传入顺序和二叉树的层次遍历顺序一致的(核心思路)
         1.用一个数组模拟队列, 进行层次遍历,把第一个节点放入到队列中,
         2.取出队列中第一个元素, 如果数组有后续,就生成一个节点,设置为左孩子
         3.下标增加,如果数组还有后续,就生成一个节点,设置为右孩子
         4.循环2,3步,直到传入数组遍历完成

@interface TreeNode : NSObject

/// 根据数组生成一个完全二叉树
+ (TreeNode *)nodeWithDataArray:(NSArray *)dataArray;
/// 生成一个节点,左右节点为nil
+ (TreeNode *)nodeWithData:(int)data;
/// 生成一个节点,左右节点为指定节点
+ (TreeNode *)nodeWithData:(int)data leftNode:(TreeNode *)leftNode rightNode:(TreeNode *)rightNode;

@property (nonatomic, assign) int data;
@property (nonatomic, strong) TreeNode * leftNode;
@property (nonatomic, strong) TreeNode * rightNode;

@end

-------
#import "TreeNode.h"

@implementation TreeNode

// 实现方式1:根据完全二叉树的下标(1~n)来处理, 任意子节点的下标/2 都是父节点
+ (TreeNode *)nodeWithDataArray:(NSArray *)dataArray {
    if (dataArray == nil || dataArray.count == 0) {
        return nil;
    }

    //根据数组的数量,生成一个完全二叉树
    NSMutableArray<TreeNode *> * treeArray = [NSMutableArray array];
    //放一个占位的值,这样根节点的下标就对应成treeArray[1]了,计算父节点会更容易点
    [treeArray addObject:[TreeNode nodeWithData:NAN]];
    for (int i = 0; i<dataArray.count; i++) {
        NSNumber * num = dataArray[i];
        TreeNode * temp = [TreeNode nodeWithData:num.intValue];
        // 如果是偶数,说明是对应父节点的左子节点
        if (treeArray.count%2==0&&treeArray.count>1) {
            TreeNode * father = treeArray[treeArray.count/2];
            father.leftNode = temp;
        }
        // 如果是奇数,说明是对应父节点的右子节点
        if (treeArray.count%2==1) {
            TreeNode * father = treeArray[treeArray.count/2];
            father.rightNode = temp;
        }
        [treeArray addObject:temp];

    }

    return treeArray[1];

}

/// 实现方式2:模拟层次遍历, 依次生成子节点并赋值
+ (TreeNode *)nodeWithDataArray2:(NSArray<NSNumber *> *)dataArray {
    if (dataArray == nil || dataArray.count == 0) {
        return nil;
    }
    
    //模拟队列结构,进行层次遍历
    NSMutableArray<TreeNode *> * treeArray = [NSMutableArray array];
    
    TreeNode * root = [TreeNode nodeWithData:dataArray.firstObject.intValue];
    [treeArray addObject:root];
    for (int i = 1; i<dataArray.count; i++) {
        NSNumber * num = dataArray[i];
        TreeNode * leftNode = [TreeNode nodeWithData:num.intValue];
        TreeNode * father = treeArray.firstObject;
        [treeArray removeObject:father];

        father.leftNode = leftNode;
        [treeArray addObject:leftNode];
        i++;
        if (i>=dataArray.count) {
            break;
        }
        num = dataArray[i];
        TreeNode * rightNode = [TreeNode nodeWithData:num.intValue];
        father.rightNode = rightNode;
        [treeArray addObject:rightNode];
        
    }
    
    return root;
    
}

+ (TreeNode *)nodeWithData:(int)data {
    TreeNode * root = [[TreeNode alloc] init];
    root.data = data;
    return root;
}

+ (TreeNode *)nodeWithData:(int)data leftNode:(TreeNode *)leftNode rightNode:(TreeNode *)rightNode {
    TreeNode * root = [[TreeNode alloc] init];
    root.data = data;
    root.leftNode = leftNode;
    root.rightNode = rightNode;
    return root;
    
}

- (NSString *)description {
    return [NSString stringWithFormat:@"%d %@ %@",self.data,self.leftNode,self.rightNode];
}


@end

到此,我们可以很方便的生成一个二叉树了, 然后开始处理二叉树镜像. 类似于这样的, 对于根节点来说, 就是左右孩子的值进行一次交换, 然后递归左子树,递归右子树.


- (void)viewDidLoad {
    [super viewDidLoad];


    [self mirrorTree];   
    
}
/// 二叉树镜像
- (void)mirrorTree {
    
    TreeNode * root = [TreeNode nodeWithDataArray:@[@(8),@(6),@(10),@(5),@(7),@(9),@(11)]];
    NSLog(@"%@",root);
    [self __mirrorAction:root];
    NSLog(@"%@",root);
    
}

- (void)__mirrorAction:(TreeNode *)root {
    if (root.leftNode == nil && root.rightNode == nil) {
        return;
    }
    // 左右节点交换值
    TreeNode * temp = root.leftNode;
    root.leftNode = root.rightNode;
    root.rightNode = temp;
    // 递归调用左子树
    if (root.leftNode) {
        [self __mirrorAction:root.leftNode];
    }
    // 递归调用右子树
    if (root.rightNode) {
        [self __mirrorAction:root.rightNode];
    }
    
    
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值