Swift2.2 看完这篇博客 你不想懂也会懂得----二叉树
一:初衷
我自己也好奇,为什么莫名其妙的想起写这个,其实数据里面包含的结构和逻辑我自己觉得才是最原始经典的,最近也在学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 ...
随机推荐
- php学习记录
放了寒假.期末考试折腾了一个月都不会写代码了. 一放寒假就找了套PHP培训的课程 在这做些笔记,系统的学习一下php 2017.1.14 介绍集成环境---wamp Apache服务器根目录 / -- ...
- 适用于SQl数据的Sql语句
---基础知识if exists(select * from sysdatabases where name='Exam') ---判断数据库中是否存在该数据库drop database Examgo ...
- shell 实例学习
安装crond:yum install crontabs (http://blog.163.com/victory_wxl/blog/static/14130530220115296180333/) ...
- 转化秒数为正规的时间格式{NSString格式的秒数转成NSDate格式后再以NSString形式输出)
-(NSString*)changeNumToTime:(NSString*)str { NSDate *date = [NSDate dateWithTimeIntervalSince1970:[s ...
- 单位冲击响应与频响以及FIR实现代码(C语言)(转)
源:FIR数字滤波器C语言 1.单位冲击响应与频响 就如同之前所说的一样,使用下图所示的单位冲击响应,所设计的滤波器,是无法实现的. 现在,让我们看看其这个滤波器的频响.所谓频响,就是计算其单位冲击响 ...
- Unknown/unsupported storage engine: InnoDB
症状:无法启动mysql,在“mysql数据库目录/主机名.err”日志文件中报错 Unknown/unsupported storage engine: InnoDB原因:MySQL5.5.8 GA ...
- Mysql的收获
今天公司的业务需求中,遇到一个很郁闷的情况. 有一个申请记录,缺少申请原因的字段. 我以为很简单,采用left jion 很容易获取到申请原因. SELECT a.*,b.RealName,c.Dep ...
- ubuntu内核的编译安装
原创声明:转载请注明出处. 一.操作环境: 1.ubuntu版本 2.linux原有内核版本 3.要安装的linux内核版本 linux-3.16.39 二.新内核的编译和安装 1.首先下载linux ...
- 最新的thinkphp 后台入口的问题
新的thinkphp后台入口绑定了单独了文件 admin.php 要注意.
- PreparedStatement接口
从实际来讲,Statement现在已经不使用了,他已经称为了历史. Statement执行关键性问题在于他需要一个完整 的字符串定义要使用的SQL语句,而PreparedStatement可以动态的设 ...