有一颗二叉树,最大深度为D,所以有2^D-1个节点。
【本题中学到的有】
- 2^D在C中的表示,用了一个很巧妙地方法 1<<D
<<是左移运算符,x<<y为x*2^y - while(scanf("%d%d",&a,&b)==2)
二元输入老套路了 - 路径存储,我这里用了一个vector试了一下,但是用到c++的stl显然会比较慢,所以我注释掉的printf部分从输出来说还可以。
如果不clear的话,vector是可以一直存储路径下去的。
另外,我本来想做一个多维数组来保存每一条路径。但是由于数组最开始需要声明整体内存大小,不能用后来读取的变量,所以放弃了。(s1是本来想使用但是失败了的)
【源码】
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
//树高D最大为20
const int maxn = 20;
//最大节点个数为1<<maxn
//数组s用于记录每个节点当前的开关状态,0表示关,向左;1表示开,向右
int s[1<<maxn]; //用于存储每个点的开关
vector<int> ss; //用于存储一条路径
int main(){
int D,I;
while(scanf("%d%d",&D, &I)==2){
//输入一组数据,D深的树,I个待检数据
int n = (1<<D)-1;
int k = 0;
//0表示关,向左;1表示开,向右。每一层下一个的左节点为自己*2,右节点为自己*2+1
//-> 下一层的节点为【自己*2+自己的开关值】
memset(s,0,sizeof(s)); //清空数组,全部置零,全部为关;
for (int i = 0; i < I; i++){
//开始考察每个小球
//memset(s1,0,sizeof(s1));
k = 1;
ss.clear();
for (int j = 0; j < D; j++){
k = 2*k + s[k-1];
s[k-1] = !s[k-1];
ss.push_back(k);
//printf("%d ",k);
}
//vector输出必须通过迭代器
for (vector<int>::iterator i=ss.begin(); i!=ss.end(); i++){
cout << *i << " ";
}
cout << endl;
}
}
system("pause");
}
【代码示例】
五层树的三个球情况:
书中给出了第二个方法:根据考察的第I个小球的数字编号来看落在哪里。
这个方法完全是数学想法,根据这个编号的数字来看。
对于根节点1号,由于每个球都要经过,所以根节点上的第I个经过的,如果I是奇数,那么就是往左走,如果I是偶数,那么就是往右走。
当I是奇数的时候,它是往左走的第(I+1)/2个小球。
当I是偶数的时候,它是往右走的第I/2个小球。
也就是对于下一个节点:
【左】如果(I+1)/2是奇数,那再往左走;
【右】如果I/2是偶数,那再往右走。
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
//树高D最大为20
//const int maxn = 20;
//最大节点个数为1<<maxn
//数组s用于记录每个节点当前的开关状态,0表示关,向左;1表示开,向右
//int s[1<<maxn]; //用于存储每个点的开关
//vector<int> ss; //用于存储一条路径
int main(){
int D,I;
while(scanf("%d%d",&D, &I)==2){
//输入一组数据,D深的树,I个待检数据
int n = (1<<D)-1;
//int k = 0;
int k = 1;
for (int i = 0; i < D; i++){
printf("%d ",k);
if(I%2) { k = k*2; I = (I+1)/2; }
else { k = k*2+1; I /= 2;}
}
//0表示关,向左;1表示开,向右。每一层下一个的左节点为自己*2,右节点为自己*2+1
//-> 下一层的节点为【自己*2+自己的开关值】
//memset(s,0,sizeof(s)); //清空数组,全部置零,全部为关;
/*
for (int i = 0; i < I; i++){
//开始考察每个小球
//memset(s1,0,sizeof(s1));
k = 1;
ss.clear();
for (int j = 0; j < D; j++){
k = 2*k + s[k-1];
s[k-1] = !s[k-1];
ss.push_back(k);
//printf("%d ",k);
}
//vector输出必须通过迭代器
for (vector<int>::iterator i=ss.begin(); i!=ss.end(); i++){
cout << *i << " ";
}
cout << endl;
}
*/
}
system("pause");
}