Swift2.2 看完这篇博客 你不想懂也会懂得----二叉树

时间:2022-09-05 19:43:58

一:初衷

我自己也好奇,为什么莫名其妙的想起写这个,其实数据里面包含的结构和逻辑我自己觉得才是最原始经典的,最近也在学swift,就向着利用swift整理一些二叉树。自己刚开始的时候也是用OC看着别的小伙伴的博客在写的,OC的逻辑是理清楚了,但用swift去写的时候,遇到些许问题,不是逻辑上的问题,就是语法问题。经过这两天的这个二叉树遇到的问题发现,还是觉得基础不够扎实。以为最基本的掌握了,其实不然,有好多东西还是欠火候!还是得静下心,就从最基本的开始吧!不知道有没有和我一样的小伙伴,基础你真的打好了吗?哈哈··

二:先利用OC写二叉树基本的创建和遍历

你可以先学习一些这些基本的一些概念,什么是二叉树,二叉树遍历的分类和基本规则。

1 二叉树的概念:点击—这是度娘给的答案,还是挺完整的,不知道的可以去看看它的基本概念和一些基本的性质

2 二叉树的深度和宽度(下面代码有具体的说到)

3 二叉树遍历: 先序遍历   中序遍历   后序遍历   层次遍历 (这也是在度娘找的,答案很精辟)

Swift2.2 看完这篇博客 你不想懂也会懂得----二叉树

三:OC 二叉树代码(从.H 文件到 .M 文件 再到 调用方法的顺序)

下面是  ZXTThreeObject.h 整个文件的代码,整个文件方便学习。里面思路的整理解释我全都加在代码注释里面了,仔细阅读就OK。

//  Created by mxsm on 16/3/30.
//  Copyright © 2016年 mxsm. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface ZXTThreeObject : NSObject

// 值
@property(nonatomic,assign)NSInteger Value;

// 左节点
@property(nonatomic,strong) ZXTThreeObject * leftTreeNode;

// 右节点
@property(nonatomic,strong) ZXTThreeObject * rightTreeNode;

/*
      基本方法
 */

//  创建二叉树
+(ZXTThreeObject * )CreatTreesWithValues:(NSArray * )Values;

//  计算二叉树的深度
+(NSInteger)DepthOfTree:(ZXTThreeObject * ) RootNode;

//  计算二叉树的宽度
+(NSInteger)WidthOfTree:(ZXTThreeObject * )RootNode;

//  先序遍历二叉树
+(void)XianXuBianLTreeNode:(ZXTThreeObject * ) RootTreeNode handle:(void(^)(ZXTThreeObject *  Treenode))handle;

//  中序遍历二叉树
+(void)ZhongXuBLTreeNode:(ZXTThreeObject * ) RootTreeNode handle:(void(^)(ZXTThreeObject *  Treenode))handle;

//  后序遍历二叉树
+(void)HouXuBLTreeNode:(ZXTThreeObject * ) RootNode handle:(void (^)(ZXTThreeObject *  treenode))handle;

//  层次遍历
+(void)CengCiBLTreeNode:(ZXTThreeObject * ) RootNode handle:(void(^)(ZXTThreeObject * treenode))handle;

@end

下面是 ZXTThreeObject.m 的文件

//
//  ZXTThreeObject.m
//  sinatest
//
//  Created by mxsm on 16/3/30.
//  Copyright © 2016年 mxsm. All rights reserved.
//

#import "ZXTThreeObject.h"

@implementation ZXTThreeObject

/* 

    创建二叉树

*/

+(ZXTThreeObject * )CreatTreesWithValues:(NSArray * )Values
{

    ZXTThreeObject * RootNode = nil;

    for (NSInteger  i =0 ; i < Values.count; i++)
    {
        NSInteger  vlaue = [Values[i]integerValue];
        // 一直返回的是根节点
        RootNode = [ZXTThreeObject  addTreeNode:RootNode values:vlaue];
    }

    return  RootNode;
}

#pragma mark  添加节点
+(ZXTThreeObject * ) addTreeNode:(ZXTThreeObject * )treeNode  values:(NSInteger)value
{

    if (!treeNode) {

        treeNode=[[ZXTThreeObject alloc]init];
        treeNode.Value=value;
        NSLog(@"节点:%ld",(long)value);
    }

    // value 值小于 节点的值 插入 左节点
    else if (value <= treeNode.Value)
    {
        NSLog(@"-------to left");
        treeNode.leftTreeNode = [self addTreeNode:treeNode.leftTreeNode values:value];

    }
    // 否则就是右边的节点值
    else
    {
        NSLog(@"=======to right");
        treeNode.rightTreeNode = [self addTreeNode:treeNode.rightTreeNode values:value];
    }

    NSLog(@"返回节点的值:%ld",(long) treeNode.Value);
    return treeNode;

    /*
        这里调用的思想是递归的思想,递归大家应该都理解,但我不知道有多少孩纸和我一样,刚开始不理解其中的运行过程。
        你要是理解了其中的运行过程,你也就理解了他的创建。。
    */
    /*  这里返回的 treeNode 这个参数其实是一个局部变量,不管上面嵌套调用多少次

        +(ZXTThreeObject * ) addTreeNode:(ZXTThreeObject * )treeNode  values:(NSInteger)value

        这个方法,这里返回值 一次返回的一直都是 它的 最原始的根节点!!
       (很重要,但如果返回值你写成全局变量就不一样了,他返回的就是最后赋给它的值)
       (这里简单说一下,局部变量是存储在 栈 中的,全局变量是存储在静态存储区的!!每存储一个局部变量,编译器就会开辟一块 栈区域来保存 方法第一次传递的 treeNode 这个变量,编译器就开辟了 栈区域保存了它的值,后面要是有嵌套调用了这个方法,编译器就又开辟新的栈区域保存他们的返回值,但不会影响第一次保存的值,你要调用多次的话,第一个保存的值也就是最后一个返回的了,这就解释了为什么每次最后的返回值都是 最原始的根节点了!)

        NSArray * array= @[@"15",@"14",@"16",@"13",@"17",@"18",@"9",@"20",@"16",@"12",@"21",@"22",@"10",@"26",@"1"];
        root= [ZXTThreeObject  CreatTreesWithValues:array];

 **  以上面创建的数组为例  不管嵌套调用多少次,最后返回的 任然是 @“15” 这个节点,下面是打印的值!!
     2016-04-05 11:57:29.532 sinatest[2005:339019] 节点:15
     2016-04-05 11:57:29.532 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.532 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.532 sinatest[2005:339019] 节点:14
     2016-04-05 11:57:29.532 sinatest[2005:339019] 返回节点的值:14
     2016-04-05 11:57:29.532 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.533 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.533 sinatest[2005:339019] 节点:16
     2016-04-05 11:57:29.533 sinatest[2005:339019] 返回节点的值:16
     2016-04-05 11:57:29.533 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.533 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.533 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.533 sinatest[2005:339019] 节点:13
     2016-04-05 11:57:29.533 sinatest[2005:339019] 返回节点的值:13
     2016-04-05 11:57:29.533 sinatest[2005:339019] 返回节点的值:14
     2016-04-05 11:57:29.533 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.533 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.534 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.534 sinatest[2005:339019] 节点:17
     2016-04-05 11:57:29.534 sinatest[2005:339019] 返回节点的值:17
     2016-04-05 11:57:29.534 sinatest[2005:339019] 返回节点的值:16
     2016-04-05 11:57:29.534 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.534 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.534 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.534 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.534 sinatest[2005:339019] 节点:18
     2016-04-05 11:57:29.534 sinatest[2005:339019] 返回节点的值:18
     2016-04-05 11:57:29.534 sinatest[2005:339019] 返回节点的值:17
     2016-04-05 11:57:29.535 sinatest[2005:339019] 返回节点的值:16
     2016-04-05 11:57:29.535 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.535 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.535 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.535 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.535 sinatest[2005:339019] 节点:9
     2016-04-05 11:57:29.535 sinatest[2005:339019] 返回节点的值:9
     2016-04-05 11:57:29.535 sinatest[2005:339019] 返回节点的值:13
     2016-04-05 11:57:29.535 sinatest[2005:339019] 返回节点的值:14
     2016-04-05 11:57:29.535 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.536 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.536 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.536 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.536 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.536 sinatest[2005:339019] 节点:20
     2016-04-05 11:57:29.536 sinatest[2005:339019] 返回节点的值:20
     2016-04-05 11:57:29.536 sinatest[2005:339019] 返回节点的值:18
     2016-04-05 11:57:29.536 sinatest[2005:339019] 返回节点的值:17
     2016-04-05 11:57:29.536 sinatest[2005:339019] 返回节点的值:16
     2016-04-05 11:57:29.536 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.537 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.537 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.537 sinatest[2005:339019] 节点:16
     2016-04-05 11:57:29.537 sinatest[2005:339019] 返回节点的值:16
     2016-04-05 11:57:29.537 sinatest[2005:339019] 返回节点的值:16
     2016-04-05 11:57:29.537 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.537 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.537 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.537 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.537 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.538 sinatest[2005:339019] 节点:12
     2016-04-05 11:57:29.538 sinatest[2005:339019] 返回节点的值:12
     2016-04-05 11:57:29.538 sinatest[2005:339019] 返回节点的值:9
     2016-04-05 11:57:29.538 sinatest[2005:339019] 返回节点的值:13
     2016-04-05 11:57:29.538 sinatest[2005:339019] 返回节点的值:14
     2016-04-05 11:57:29.538 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.538 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.538 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.538 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.538 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.539 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.539 sinatest[2005:339019] 节点:21
     2016-04-05 11:57:29.539 sinatest[2005:339019] 返回节点的值:21
     2016-04-05 11:57:29.539 sinatest[2005:339019] 返回节点的值:20
     2016-04-05 11:57:29.539 sinatest[2005:339019] 返回节点的值:18
     2016-04-05 11:57:29.539 sinatest[2005:339019] 返回节点的值:17
     2016-04-05 11:57:29.539 sinatest[2005:339019] 返回节点的值:16
     2016-04-05 11:57:29.539 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.539 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.539 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.539 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.540 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.540 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.540 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.540 sinatest[2005:339019] 节点:22
     2016-04-05 11:57:29.540 sinatest[2005:339019] 返回节点的值:22
     2016-04-05 11:57:29.540 sinatest[2005:339019] 返回节点的值:21
     2016-04-05 11:57:29.540 sinatest[2005:339019] 返回节点的值:20
     2016-04-05 11:57:29.540 sinatest[2005:339019] 返回节点的值:18
     2016-04-05 11:57:29.540 sinatest[2005:339019] 返回节点的值:17
     2016-04-05 11:57:29.540 sinatest[2005:339019] 返回节点的值:16
     2016-04-05 11:57:29.541 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.541 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.541 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.541 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.541 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.541 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.541 sinatest[2005:339019] 节点:10
     2016-04-05 11:57:29.541 sinatest[2005:339019] 返回节点的值:10
     2016-04-05 11:57:29.541 sinatest[2005:339019] 返回节点的值:12
     2016-04-05 11:57:29.541 sinatest[2005:339019] 返回节点的值:9
     2016-04-05 11:57:29.541 sinatest[2005:339019] 返回节点的值:13
     2016-04-05 11:57:29.542 sinatest[2005:339019] 返回节点的值:14
     2016-04-05 11:57:29.542 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.542 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.542 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.542 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.542 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.542 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.542 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.542 sinatest[2005:339019] =======to right
     2016-04-05 11:57:29.542 sinatest[2005:339019] 节点:26
     2016-04-05 11:57:29.543 sinatest[2005:339019] 返回节点的值:26
     2016-04-05 11:57:29.543 sinatest[2005:339019] 返回节点的值:22
     2016-04-05 11:57:29.543 sinatest[2005:339019] 返回节点的值:21
     2016-04-05 11:57:29.543 sinatest[2005:339019] 返回节点的值:20
     2016-04-05 11:57:29.543 sinatest[2005:339019] 返回节点的值:18
     2016-04-05 11:57:29.543 sinatest[2005:339019] 返回节点的值:17
     2016-04-05 11:57:29.543 sinatest[2005:339019] 返回节点的值:16
     2016-04-05 11:57:29.543 sinatest[2005:339019] 返回节点的值:15
     2016-04-05 11:57:29.543 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.543 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.544 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.544 sinatest[2005:339019] -------to left
     2016-04-05 11:57:29.544 sinatest[2005:339019] 节点:1
     2016-04-05 11:57:29.544 sinatest[2005:339019] 返回节点的值:1
     2016-04-05 11:57:29.544 sinatest[2005:339019] 返回节点的值:9
     2016-04-05 11:57:29.544 sinatest[2005:339019] 返回节点的值:13
     2016-04-05 11:57:29.544 sinatest[2005:339019] 返回节点的值:14
     2016-04-05 11:57:29.544 sinatest[2005:339019] 返回节点的值:15

     */

}

#pragma mark  计算二叉树的深度

/*
 二叉树的深度定义为:从 根节点 到 叶子节点 依次经过的节点形成树的一条路径,  最长路径  的长度为树的深度!

 1)如果根节点为空,则深度为0;

 2)如果左右节点都是空,则深度为1;

 3)递归思想:二叉树的深度=max(左子树的深度,右子树的深度)+ 1

 */

+(NSInteger)DepthOfTree:(ZXTThreeObject * ) RootNode
{

    if (!RootNode) {

        return 0;

    }
    else if (!RootNode.leftTreeNode && !RootNode.rightTreeNode)
    {

        return 1;

    }
    else
    {
        NSInteger leftDepth =  [self DepthOfTree:RootNode.leftTreeNode];
        NSInteger rightDepth =  [self DepthOfTree:RootNode.rightTreeNode];
        return MAX(leftDepth, rightDepth) + 1;
    }

}

#pragma mark 二叉树宽度
/*

    二叉树宽度的定义:各层节点数的最大值!

 */
+(NSInteger)WidthOfTree:(ZXTThreeObject * )RootNode
{
    // 根节点不存在,就返回 0
    if (!RootNode) {

        return 0;
    }

    /*
        这里这层次遍历有点相似的味道在里面,但不是说完全相同,理解学习思路。
    */

    NSMutableArray * queeArray = [NSMutableArray array];
    NSInteger currentWidth = 0;
    NSInteger maxWidth = 1;// 前面 0 的不存在就 肯定有,至少是 1
    [queeArray addObject:RootNode]; // 添加根节点

    while (queeArray.count > 0) {

        currentWidth=queeArray.count;// 这就是当前的节点的数目,第一层就只有根节点 宽度是1 ,下一层,按照下面逻辑添加了左右节点就变成了 2

        // 遍历该层,删除原始数组中遍历过的节点,添加它下一层的节点。再循环遍历
        for (NSInteger i=0; i<currentWidth; i++) {

            ZXTThreeObject * treenode = [queeArray firstObject];

            [queeArray removeObjectAtIndex:0];

            if (treenode.leftTreeNode) {

                [queeArray addObject:treenode.leftTreeNode];

            }
            if (treenode.rightTreeNode) {

                [queeArray addObject:treenode.rightTreeNode];

            }

        }
        // 一层一层的遍历的时候去最大值,返回
        maxWidth = MAX(maxWidth, queeArray.count);

    }

    return maxWidth;
}

/*

 先序遍历
 下面是遍历的结果;
 2016-04-05 10:31:16.627 sinatest[1707:294999] 先序遍历结果:15,14,13,9,1,12,10,16,16,17,18,20,21,22,26
 2016-04-05 10:31:16.628 sinatest[1707:294999] 中序遍历结果:1,9,10,12,13,14,15,16,16,17,18,20,21,22,26
 2016-04-05 10:31:16.629 sinatest[1707:294999] 后序遍历结果:1,10,12,9,13,14,16,26,22,21,20,18,17,16,15
 2016-04-05 10:31:16.629 sinatest[1707:294999] 层次遍历结果:15,14,16,13,16,17,9,18,1,12,20,10,21,22,26

*/

+(void)XianXuBianLTreeNode:(ZXTThreeObject * ) RootTreeNode handle:(void(^)(ZXTThreeObject *  Treenode))handle
{

    if (RootTreeNode) {

        if (handle) {

            handle(RootTreeNode);

        }

        // 基本的顺序就是 根节点 --> 左节点  --> 右节点
        // 这里这样子调用就有一个方法执行顺序的问题,这样子写嵌套进去方法调用的过程正好就是先序遍历的顺序。
        // 下面的中序遍历 和 后序遍历 都是同样的道理。
        // 这里的 先 中 后 理解成根节点在遍历过程中的位置就理解了,比如 先序遍历,就是根节点在最前面 中序遍历,就是根节点在中间
        [self  XianXuBianLTreeNode:RootTreeNode.leftTreeNode handle:handle];

        [self  XianXuBianLTreeNode:RootTreeNode.rightTreeNode handle:handle];

    }

}

/*

  中序遍历

 */

+(void)ZhongXuBLTreeNode:(ZXTThreeObject * ) RootTreeNode handle:(void(^)(ZXTThreeObject *  Treenode))handle
{
    if (RootTreeNode) {

        [self ZhongXuBLTreeNode:RootTreeNode.leftTreeNode handle:handle];
        if (handle) {

            handle(RootTreeNode);

        }

        [self ZhongXuBLTreeNode:RootTreeNode.rightTreeNode handle:handle];
    }

}

/*

     后序遍历

 */

+(void)HouXuBLTreeNode:(ZXTThreeObject * ) RootNode handle:(void (^)(ZXTThreeObject *  treenode))handle
{
    if (RootNode) {

        [self HouXuBLTreeNode:RootNode.leftTreeNode handle:handle];

        [self HouXuBLTreeNode:RootNode.rightTreeNode handle:handle];

        if (handle) {

            handle(RootNode);

        }
    }
}

/*

      层次遍历
      层次遍历,就是一层一层的遍历,下面的方法用到了队列的想法。

*/

+(void)CengCiBLTreeNode:(ZXTThreeObject * ) RootNode handle:(void(^)(ZXTThreeObject * treenode))handle
{

    if (RootNode) {

        NSMutableArray * queeArray=[NSMutableArray array];
        // 添加了根节点进去
        [queeArray addObject:RootNode];

        while (queeArray.count>0) {

            // 取出数组中的第一个元素
            ZXTThreeObject * rootnode = [queeArray firstObject];
            if (handle) {

                // 添加这个元素的值到数组中去,这个就结合调用时候的BLOCK去研究,就明白了。
                handle(rootnode);

            }
            // 添加完这个元素的值就把这个元素删除了
            [queeArray removeObjectAtIndex:0];

            // 这个节点要有左节点的话,就添加左节点到数组中去,有右节点的话就添加右节点到数组中去。
            // 建议一步一步研究这个添加顺序,就可以清晰的看到这个是一层一层的遍历到的。
            if (rootnode.leftTreeNode) {

                [queeArray addObject:rootnode.leftTreeNode];

            }
            if (rootnode.rightTreeNode) {

                [queeArray addObject:rootnode.rightTreeNode];

            }

        }

    }

}

@end

下面是它的调用,也是粘贴了整个文件的代码,它的遍历方法是写在这个按钮点击事件里面了,没什么其他意思。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    UIButton * button=[UIButton buttonWithType:UIButtonTypeCustom];
    button.frame=CGRectMake(100, 100, 100, 40);
    [button addTarget:self action:@selector(button ) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"开始" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor purpleColor] forState:UIControlStateNormal];
    [self.view addSubview:button];

    // 数据源
    NSArray * array= @[@"15",@"14",@"16",@"13",@"17",@"18",@"9",@"20",@"16",@"12",@"21",@"22",@"10",@"26",@"1"];
    root= [ZXTThreeObject  CreatTreesWithValues:array];

}

-(void)setUI
{
    [self.delegate younameis:@"caoxiaocao"];

}

-(void)button
{

    // 二叉树的深度
    NSInteger depth =[ZXTThreeObject DepthOfTree:root];
    NSLog(@"二叉树深度:%ld",depth);

    NSInteger width =[ZXTThreeObject WidthOfTree:root];
    NSLog(@"二叉树宽度:%ld",width);

    // 先序遍历调用
    NSMutableArray *orderArray = [NSMutableArray array];
    [ZXTThreeObject XianXuBianLTreeNode: root handle:^(ZXTThreeObject * Treenode) {

        [orderArray addObject:@(Treenode.Value)];

    }];
    NSLog(@"先序遍历结果:%@", [orderArray componentsJoinedByString:@","]);

    // 中序遍历调用
    NSMutableArray *ordertwoArray = [NSMutableArray array];
    [ZXTThreeObject ZhongXuBLTreeNode:root handle:^(ZXTThreeObject *Treenode) {

        [ordertwoArray addObject:@(Treenode.Value)];

    }];
    NSLog(@"中序遍历结果:%@", [ordertwoArray componentsJoinedByString:@","]);

    // 后序遍历调用
    NSMutableArray *orderthreeArray = [NSMutableArray array];
    [ZXTThreeObject HouXuBLTreeNode:root handle:^(ZXTThreeObject *Treenode) {

        [orderthreeArray addObject:@(Treenode.Value)];

    }];
    NSLog(@"后序遍历结果:%@", [orderthreeArray componentsJoinedByString:@","]);

    // 层次遍历调用
    NSMutableArray *orderfourArray = [NSMutableArray array];
    [ZXTThreeObject CengCiBLTreeNode:root handle:^(ZXTThreeObject *Treenode) {

        [orderfourArray addObject:@(Treenode.Value)];

    }];
    NSLog(@"层次遍历结果:%@", [orderfourArray componentsJoinedByString:@","]);

}

四:利用swift创建二叉树

用swift创建二叉树,原理和上面的是一样的,可能就是语法细节的把握,注意细节,还有,好好学习。哈哈··

import UIKit

class ZXTreeNode: NSObject {

    var  Value:Int?
    var  leftNode:ZXTreeNode?
    var  rightNode:ZXTreeNode?

    class  func creatTreeNode(RooeNodeArray:[Int]) -> ZXTreeNode {

        var  root:ZXTreeNode?
        for i in 0..<RooeNodeArray.count
        {
            let  value = RooeNodeArray[i]
            root = self.addTreeNode(&root, value: value)
        }

        return root!

    }

    class func addTreeNode( inout  RootNode:ZXTreeNode?,value:Int ) -> ZXTreeNode {

        if (RootNode == nil ) {

            RootNode = ZXTreeNode()
            RootNode!.Value = value
            print("节点:",RootNode!.Value)

        } // 值小于根节点的值,插左边
        else if (value <= RootNode!.Value)
        {
            print("----- to left ")
            addTreeNode(&RootNode!.leftNode, value: value)

        }
        else
        {
            print("----- to right")
            addTreeNode(&RootNode!.rightNode, value: value)
        }

        return RootNode!
    }
}

后序还会更新它的遍历方式

Swift2.2 看完这篇博客 你不想懂也会懂得----二叉树的更多相关文章

  1. &lbrack;转帖&rsqb;看完这篇文章,我奶奶都懂了https的原理

    看完这篇文章,我奶奶都懂了https的原理 http://www.17coding.info/article/22 非对称算法 以及 CA证书 公钥 核心是 大的质数不一分解 还有 就是 椭圆曲线算法 ...

  2. 看完这篇文章,我奶奶都懂了https的原理

    本文在个人技术博客同步发布,详情可猛戳 亦可扫描屏幕右方二维码关注个人公众号 Http存在的问题   上过网的朋友都知道,网络是非常不安全的.尤其是公共场所很多免费的wifi,或许只是攻击者的一个诱饵 ...

  3. 第一篇博客 ---- 分享关于Maven使用的一些技巧

    Maven环境搭建 在官网上下载maven安装包,地址:http://maven.apache.org/download.cgi . 解压文件到电脑坐在盘符目录,如E:\apache-maven-3. ...

  4. 第一篇博客:Hello World

    2016年10月10日,双十,好日子,决定开始写第一篇博客,标题想了会,就叫Hello World 吧,哈哈^_^. 首先感谢博客园的管理们能批准我的申请,记得在14年的时候申请过一次,竟然没申请通过 ...

  5. &lbrack;书籍&rsqb;值得纪念的第100篇博客,推荐一些看过的UI书籍

    1. 前言 来到博客园11年,这两年闲下来了才有时间写写博客,不知不觉终于写到第100篇博客了.回顾过去发表的博客,居然大部分都与UI相关.明明我本来从事的是Oracle的相关开发,明明我当初的目标是 ...

  6. 鸿蒙内核源码分析&lpar;任务切换篇&rpar; &vert; 看汇编如何切换任务 &vert; 百篇博客分析OpenHarmony源码 &vert; v41&period;03

    百篇博客系列篇.本篇为: v41.xx 鸿蒙内核源码分析(任务切换篇) | 看汇编如何切换任务 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁 ...

  7. 鸿蒙内核源码分析&lpar;编译环境篇&rpar; &vert; 编译鸿蒙看这篇或许真的够了 &vert; 百篇博客分析OpenHarmony源码 &vert; v50&period;06

    百篇博客系列篇.本篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙防掉坑指南 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙防掉 ...

  8. Hello World -- 第一篇博客

    今年注定是不寻常的一年,因为技术,接触了许多大牛.通过一篇篇博文,看到了大牛们勤奋好学.孜孜不倦的精神,于是决定也开个博客,向大牛学习. 博客开了,写点什么呢?奈何肚子里墨水不多,吐出来也多是白沫,不 ...

  9. 看完这篇还不会 GestureDetector 手势检测,我跪搓衣板!

    引言 在 android 开发过程中,我们经常需要对一些手势,如:单击.双击.长按.滑动.缩放等,进行监测.这时也就引出了手势监测的概念,所谓的手势监测,说白了就是对于 GestureDetector ...

随机推荐

  1. nodejs中使用http请求返回值为html时乱码问题

    今天用nodejs进行http请求时返回的数据是一个html文件,然后我还是按照以前解析json数据的方法.果不其然报错了:SyntaxError: Unexpected token  in JSON ...

  2. Kruskal最小生成树

    并查集+kruskal==>MST 效率很低 #include <iostream> using namespace std; #define MAX 105 //自己设置最大值 / ...

  3. BZOJ&lowbar;1208&lowbar;&amp&semi;&lowbar;Codevs&lowbar;1258&lowbar;&lbrack;HNOI2004&rsqb;&lowbar;宠物收养所&lowbar;&lpar;平衡树&sol;set&rpar;

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1208 (据说codevs要更新?就不放codevs的地址了吧...) 有宠物和人,每个单位都有 ...

  4. matlab函数:c2d离散化函数(待完善)

    Convert model from continuous to discrete time sysd =c2d(sys,Ts)sysd =c2d(sys,Ts,method)sysd =c2d(sy ...

  5. java内存模型1

    并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信 ...

  6. PHP 中的CURL 模拟表单的post提交

    废话不多说啦,直接上代码: <?php $data = ['username'=>'乔峰','skill'=>'擒龙手']; $headers = array('Content-Ty ...

  7. Spring基础2

    一.Spring属性注入 1)构造方法属性注入 2)set方法属性注入:通过在bean对象所属类中提供相应字段的set方法,并在配置文件中配置<property.....> <bea ...

  8. &lbrack;Android&rsqb; Activity间切换,传递数据

    前面照着android系统的裁剪图片的功能自己写了一个相似的工具.功能是大体上实现了,但留下了一个调用的问题:如何从我的程序调用这个裁剪工具,并且获得裁剪后的图片呢? 其实这个也很简单了,就是inte ...

  9. Android getScrollX&lpar;&rpar;详解

    在开发中相信大家在自定义View时会时不时的使用getScrollX()方法,为了便于之后的开发工作,本篇博客主要记录了我对getScrollX()方法的理解. getScrollX:Return t ...

  10. python的ftplib模块

    Python中的ftplib模块 Python中默认安装的ftplib模块定义了FTP类,其中函数有限,可用来实现简单的ftp客户端,用于上传或下载文件 FTP的工作流程及基本操作可参考协议RFC95 ...