一:初衷
我自己也好奇,为什么莫名其妙的想起写这个,其实数据里面包含的结构和逻辑我自己觉得才是最原始经典的,最近也在学swift,就向着利用swift整理一些二叉树。自己刚开始的时候也是用OC看着别的小伙伴的博客在写的,OC的逻辑是理清楚了,但用swift去写的时候,遇到些许问题,不是逻辑上的问题,就是语法问题。经过这两天的这个二叉树遇到的问题发现,还是觉得基础不够扎实。以为最基本的掌握了,其实不然,有好多东西还是欠火候!还是得静下心,就从最基本的开始吧!不知道有没有和我一样的小伙伴,基础你真的打好了吗?哈哈··
二:先利用OC写二叉树基本的创建和遍历
你可以先学习一些这些基本的一些概念,什么是二叉树,二叉树遍历的分类和基本规则。
1 二叉树的概念:点击—这是度娘给的答案,还是挺完整的,不知道的可以去看看它的基本概念和一些基本的性质。
2 二叉树的深度和宽度(下面代码有具体的说到)
3 二叉树遍历: 先序遍历 中序遍历 后序遍历 层次遍历 (这也是在度娘找的,答案很精辟)
三: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 看完这篇博客 你不想懂也会懂得----二叉树的更多相关文章
-
[转帖]看完这篇文章,我奶奶都懂了https的原理
看完这篇文章,我奶奶都懂了https的原理 http://www.17coding.info/article/22 非对称算法 以及 CA证书 公钥 核心是 大的质数不一分解 还有 就是 椭圆曲线算法 ...
-
看完这篇文章,我奶奶都懂了https的原理
本文在个人技术博客同步发布,详情可猛戳 亦可扫描屏幕右方二维码关注个人公众号 Http存在的问题 上过网的朋友都知道,网络是非常不安全的.尤其是公共场所很多免费的wifi,或许只是攻击者的一个诱饵 ...
-
第一篇博客 ---- 分享关于Maven使用的一些技巧
Maven环境搭建 在官网上下载maven安装包,地址:http://maven.apache.org/download.cgi . 解压文件到电脑坐在盘符目录,如E:\apache-maven-3. ...
-
第一篇博客:Hello World
2016年10月10日,双十,好日子,决定开始写第一篇博客,标题想了会,就叫Hello World 吧,哈哈^_^. 首先感谢博客园的管理们能批准我的申请,记得在14年的时候申请过一次,竟然没申请通过 ...
-
[书籍]值得纪念的第100篇博客,推荐一些看过的UI书籍
1. 前言 来到博客园11年,这两年闲下来了才有时间写写博客,不知不觉终于写到第100篇博客了.回顾过去发表的博客,居然大部分都与UI相关.明明我本来从事的是Oracle的相关开发,明明我当初的目标是 ...
-
鸿蒙内核源码分析(任务切换篇) | 看汇编如何切换任务 | 百篇博客分析OpenHarmony源码 | v41.03
百篇博客系列篇.本篇为: v41.xx 鸿蒙内核源码分析(任务切换篇) | 看汇编如何切换任务 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁 ...
-
鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙看这篇或许真的够了 | 百篇博客分析OpenHarmony源码 | v50.06
百篇博客系列篇.本篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙防掉坑指南 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙防掉 ...
-
Hello World -- 第一篇博客
今年注定是不寻常的一年,因为技术,接触了许多大牛.通过一篇篇博文,看到了大牛们勤奋好学.孜孜不倦的精神,于是决定也开个博客,向大牛学习. 博客开了,写点什么呢?奈何肚子里墨水不多,吐出来也多是白沫,不 ...
-
看完这篇还不会 GestureDetector 手势检测,我跪搓衣板!
引言 在 android 开发过程中,我们经常需要对一些手势,如:单击.双击.长按.滑动.缩放等,进行监测.这时也就引出了手势监测的概念,所谓的手势监测,说白了就是对于 GestureDetector ...
随机推荐
-
nodejs中使用http请求返回值为html时乱码问题
今天用nodejs进行http请求时返回的数据是一个html文件,然后我还是按照以前解析json数据的方法.果不其然报错了:SyntaxError: Unexpected token in JSON ...
-
Kruskal最小生成树
并查集+kruskal==>MST 效率很低 #include <iostream> using namespace std; #define MAX 105 //自己设置最大值 / ...
-
BZOJ_1208_&;_Codevs_1258_[HNOI2004]_宠物收养所_(平衡树/set)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1208 (据说codevs要更新?就不放codevs的地址了吧...) 有宠物和人,每个单位都有 ...
-
matlab函数:c2d离散化函数(待完善)
Convert model from continuous to discrete time sysd =c2d(sys,Ts)sysd =c2d(sys,Ts,method)sysd =c2d(sy ...
-
java内存模型1
并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信 ...
-
PHP 中的CURL 模拟表单的post提交
废话不多说啦,直接上代码: <?php $data = ['username'=>'乔峰','skill'=>'擒龙手']; $headers = array('Content-Ty ...
-
Spring基础2
一.Spring属性注入 1)构造方法属性注入 2)set方法属性注入:通过在bean对象所属类中提供相应字段的set方法,并在配置文件中配置<property.....> <bea ...
-
[Android] Activity间切换,传递数据
前面照着android系统的裁剪图片的功能自己写了一个相似的工具.功能是大体上实现了,但留下了一个调用的问题:如何从我的程序调用这个裁剪工具,并且获得裁剪后的图片呢? 其实这个也很简单了,就是inte ...
-
Android getScrollX()详解
在开发中相信大家在自定义View时会时不时的使用getScrollX()方法,为了便于之后的开发工作,本篇博客主要记录了我对getScrollX()方法的理解. getScrollX:Return t ...
-
python的ftplib模块
Python中的ftplib模块 Python中默认安装的ftplib模块定义了FTP类,其中函数有限,可用来实现简单的ftp客户端,用于上传或下载文件 FTP的工作流程及基本操作可参考协议RFC95 ...