满二叉树的循环递归
一、二叉树常用性质
1. 在二叉树的第n层上最多有2 n-1个节点 。(n>=1)
2. 二叉树中如果深度为d(有k层),那么最多有2d-1个节点。(d>=1)
3. 二叉树按照从上到下从左到右依次编号,则若某节点编号为k,则其左右子树根节点编号分别为2k和2k+1;
4. 二叉树分类:满二叉树,完全二叉树
- 满二叉树:高度为h,由2^h-1个节点构成,除叶子结点外的所有结点均有两个子结点。节点数达到最大值。所有叶子结点必须在同一层上。
-
完全二叉树:
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。1 1 / \ / \ 2 3 2 3 / \ / \ / \ \ 4 5 6 4 5 6 完全二叉树 不完全二叉树
在完全二叉树中,具有n个节点的完全二叉树的深度为[log2n]+1,其中[log2n]+1是向下取整。满二叉树的深度为d=log2(n+1);
二、二叉树的循环递归规律法
2.1 例题:
有一颗满二叉树,每个节点是一个开关,初始全是关闭的,小球从顶点落下,
小球每次经过开关就会把它的状态置反,这个开关为关时,小球左跑,为开时右跑。现在问第k个球下落到d层时的开关编号。输入深度d和小球个数k
思路分析:首先该题最先想到的是模拟,开一个数组表示开关,下标表示编号,根据k的子树为2k和2k+1来改变数组,判断进行。但是这样太麻烦了。而且根据深度和小球个数,导致计算量太大。
寻找规律:
- 可以知道每一层,第奇数个落入该层的球都是往左,第偶数个落入该层的球都是往右。
- 小球按照编号依次下落的,对于左枝(也就是奇数球)k%2==1,第k号小球落入该层时,是落入该位置的第k/2 +1个小球。而偶数个k%2==0是往右走的k/2个小球
- 对于下一层左枝总计落入k/2 + k%2个球,下一层右枝总计落入k/2个小球
- 所以采取每一次一个循环,来判断k%2小球往哪儿走,循环d层,即可找出最后叶子!省去大数组和大时间
2.2 go实现
func FindPos(num, floor int) int {
// 表示进入第 floor 层,的X位置第n个球,初始化为第一层,第一个位置的第 num 个球
var floorBallPos, pos int = num, 1
// 从第一层开始计算
for i := 1; i < floor; i++ {
if floorBallPos % 2 == 1 {
// 奇数个球,全部在左边
floorBallPos = floorBallPos/2 + 1
// 此时的位置为
pos *= 2
}else {
// 偶数个球,全部在右边
floorBallPos = floorBallPos/2
// 此时的位置为
pos = pos * 2 + 1
}
}
return pos
}
人生还有意义。那一定是还在找存在的理由