题
例题6-6 小球下落 - 模拟全过程,这里有几个关于二叉树的重要结论
如果把结点从上到下从左到右编号为1,2,3……,则结点k的左右子结点编号分别为2k和2k+1 (书上原话)
将满二叉树的根结点定义第1层,则由第1层到第n层各层的结点数量,是一个首项为1,公比为2的等比数列。
#include <cstdio> #include <cstring> const int maxd = 20; int s[1 << maxd]; // 当小球在s[i]结点是应该往左还是往右 void print_tree(int ball_pos, int tree_depth) { if (tree_depth > 5) return; int no = 0, cur = 1; // 前者为结点序号,后者为当前层的结点数 for (int i = 1; i <= tree_depth; ++i) { // 逐层打印 for (int j = 1; j <= cur; ++j) { no++; if (no != ball_pos) { printf(" %3d(%c) ", no, s[no] ? 'R' : 'L'); } else { printf("[%3d(%c)]", no, s[no] ? 'R' : 'L'); } } printf(" "); cur = cur * 2; } printf("---------------------------- "); } int main() { int D, I; // D叶子深度 I小球个数 int k, n; while (scanf("%d %d", &D, &I) == 2) { printf("=== === === === === === === === "); printf("=== depth: %d === Number of balls: %d === ", D, I); printf("=== === === === === === === === "); memset(s, 0, sizeof(s)); // 初始是全部关闭的,关闭(也就是 s[i] 为 0 时)往左走 n = (1 << D) - 1; // n是最大结点编号,例如 D 为 3 时 n 就是 7 for (int i = 0; i != I; ++i) { printf("=========第 %d 个小球========== ", i + 1); k = 1; // 用 k 标识小球的当前位置 while (1) { print_tree(k, D); k = s[k] ? k * 2 + 1 : k * 2; // 1 是右,0 是左,左右取决于开关一开始的状态 s[k / 2] = !s[k / 2]; // 小球离开那个 内结点后 开关状态改变 if (k > n) break; // 小球出界 } } printf("The final position of the last ball: %d ", k / 2); // 回滚到上一层的位置 } return 0; }
参考
[1] 只有一个节点的二叉树的高度(深度)是为0还是1?_作业帮
[2] 二叉树的前两个性质没搞清楚,层和深度区别在哪里?_百度知道
[3] 满二叉树_百度百科
[4] 二叉树_百度百科
[5] 等比数列_百度搜索
[6] DEV C++编写程序出现 [errror]Id returned 1 exit status错误可能出现的原因_C/C++_YHxiaohao的博客-CSDN博客