二叉樹鏡像,根據數組生成一個完全二叉樹

額, 先看下什麼是完全二叉樹 ,
葉子只能出現在最下面的二層
最下層的葉子一定集中在左部的連續位置
倒數第二層 若有葉子結點 一定在右部連續位置
如果結點的度爲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];
    }
    
    
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章