在计算机科学中,二叉树(Binary Tree)是包含n个节点的有限集合,该集合或者为空集(此时,二叉树称为空树),或者由一个根节点和两棵互不相交的、分别称为根节点的左子树和右子树的二叉树组成。
前文
本文主要讲述了对二叉排序树的创建及其它操作,二叉排序树具有以下几个特点:1
2
3
41、若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
2、若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
3、任意节点的左、右子树也分别为二叉查找树;
4、没有键值相等的节点。
接下来我们通过用OC代码实现的方式完成对二叉排序树的一些基础操作,其中主要就是考察我们的递归思想。
首先我们以二叉树的节点为一个类创建一个类,这个类拥有两个属性,分别是左节点和右节点。如下所示:
1 | @interface DyBinaryTreeNode : NSObject |
接着,我们便可以依次定义并实现其操作方法了。
0x01 创建二叉排序树
1、创建二叉树
1 | / |
我们通过以下方法调用:1
2
3NSArray *arr = [NSArray arrayWithObjects:@(7),@(6),@(3),@(2),@(1),@(9),@(10),@(12),@(14),@(4),@(15),nil];
DyBinaryTreeNode *tree = [DyBinaryTreeNode new];
tree = [DyBinaryTreeNode createTreeWithValues:arr];
会生成如下图所示的二叉排序树:
2、获取某个位置的节点(层序)
大致思路
1、将根节点加到队列中,当队列有元素时循环。
2、循环一次将队列的第一个元素出队列,index-1
3、当index=0时返回此时的根节点。
4、遍历队列第一个元素(根节点)的左节点和右节点,加到队列中。
1 | /* @param index 按层次遍历树时的位置(从0开始算) |
调用当index==8时,打印的值为1。
1 | DyBinaryTreeNode *tree1 = [DyBinaryTreeNode treeNodeAtIndex:8 inTree:tree]; |
0x02 二叉树遍历
分为先序遍历、中序遍历、后序遍历、层序遍历。
先、中、后主要是指遍历根的顺序,如果先遍历根便是先序,其它类似。左节点和右节点的遍历顺序固定(先左后右)。
层序遍历:从上至下,从左至右依次遍历。
可参考wiki的树的遍历
1、先序遍历
先访问根,再遍历左子树,再遍历右子树。典型的递归思想。
通过block,依次将遍历到的node值回调回去。
1 | / * |
2、中序遍历
先遍历左子树,再访问根,再遍历右子树
1 | /** |
3、后序遍历
先遍历左子树,再遍历右子树,再访问根
1 | /** |
以上三种遍历方式依次打印为:
1 | 先序遍历结果:7,6,3,2,1,4,9,10,12,14,15 |
3、层序遍历
同上根据index获取节点的值的思想一样。
通过数组模拟队列,进行遍历操作。
1 | + (void)levelTraverseTree:(DyBinaryTreeNode *)rootNode handler:(void(^)(DyBinaryTreeNode *treeNode))handler { |
0x03 获取二叉树的属性
1、获取二叉树的深度
二叉树的深度
从根节点到叶子节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度包含的节点数为树的深度。
可以理解为二叉树有多少层。
递归思想:二叉树的深度 = MAX(左子树深度,右子树深度)+1
1:根节点。
1 | /* |
2、获取二叉树的宽度
队列的最大长度,结点数最多的层的结点数。
思想:同层序遍历,保存队列中最多元素时的元素个数。
1 | /* |
3、获取二叉树的节点数
递归思想:节点数=左子树节点数+右子树节点数+1(根节点)
1 | + (NSInteger)numberOfNodesInTree:(DyBinaryTreeNode *)rootNode { |
4、获取二叉树某一层的节点数
递归思想:level层节点数 = 左子树level-1层节点数+右子树level-1层节点数
1 | + (NSInteger)numberOfNodesOnLevel:(NSInteger)level inTree:(DyBinaryTreeNode *)rootNode { |
5、获取叶子节点数
叶子节点:左子树和右子树都是空的节点。
递归思想:叶子数 = 左子树叶子数 + 右子树叶子数
1 | + (NSInteger)numberOfLeafsInTree:(DyBinaryTreeNode *)rootNode { |
6、获取二叉树的最大直径
二叉树看成一个图,父子节点之间的连线看成是双向的,定义“距离”为两个节点之间的边数。
递归思想:
分为三种情况
1、最远距离经过根节点:距离 = 左子树深度 + 右子树深度
2、最远距离在根节点左子树上,即计算左子树最远距离
3、最远距离在根节点右子树上,即计算右子树最远距离
1 | + (NSInteger)maxDistanceOfTree:(DyBinaryTreeNode *)rootNode { |
0x04 翻转二叉树
又叫:二叉树的镜像。交换节点的左节点和右节点。
1、递归翻转
递归思想:先交换当前节点的左右节点,再递归调用去翻转以左右节点为根节点的二叉树。
1 | + (DyBinaryTreeNode *)invertBinaryTree:(DyBinaryTreeNode *)rootNode { |
2、非递归翻转
思想:类似于层序遍历,将即将入队列的节点交换其左右节点。
1 | /** |
备注
关于二叉树的基本算法先介绍到此处,后续会补充更多关于二叉树操作的一些算法。