J. Just Another Binary Tree
Input file: stdin Output file: stdout
Description
Mike is familiar with binary tree.
Mike likes to store binary trees into an array, from 1 to n, which means
1. 1 is the root of the tree
2. i's left child is 2i
3. i's right child is 2i+1
Mike is not satisfied with this, he wants to know the inorder(中序)traversal of the tree.
For example, n=9, the inorder traversal is " 8 4 9 2 5 14 6 3 7 ".
Mike only wants to know what the x-th number of inorder traversal is.
The inorder traversal index begins from 1, which means if n=8, x=1, the answer is 8.
Mike thinks it's too slow to calculate the whole inorder traversal, and he needs your help.
Input
The first line contains an interger T (T<=100) denoting the number of test cases.
In the following T lines, each line contains a case. In each case, there is 2 intergers x, n ( 1 <= x <= n <= 1e9 ).
You need to ouput the x-th number in the inorder traversal of a binary tree with size n.
Output
For each case, output Case #t: , to represent that this is the t-th case. And then output the answer.
Sample Input
5
100 10
100 10
100 30
100 40
100 50
Sample Output
Case #1: 34
Case #2: 18
Case #3: 39
Case #4: 10
Case #5: 44
题意
一颗 n 个结点的完全二叉树,从根从1开始编号,中序遍历它,问第 x 个遍历到的结点的编号
Source Code
#include <stdio.h>
/* 只用来算2的幂 */
int fast_pow ( int index )
{
int ans = 1,base = 2;
while( index > 0 )
{
if( index & 1 )
ans *= base;
base *= base;
index >>= 1;
}
return ans;
}
int find ( int x, int n, int depth, int root )
{
int left,right,nodeNum;
//int lack;
/*
** 先把它当成一颗满二叉树
** left和right暂时表示这棵树叶子数的一半(分开两半)
** nodeNum-1 暂时表示整颗满二叉树的全部结点数
** nodeNum-1-n 算出缺了多少个结点(原先用lack变量来装)
*/
left = right = ( nodeNum = fast_pow( depth ) ) >> 2;
//lack = nodeNum - 1 - n;
//right -= lack;
/* 完全二叉树缺结点从右边缺起,所以让right-lack */
right -= nodeNum - 1 - n;
/* 右边不够减就左边补上 */
if( right < 0 )
{
left += right;
right = 0;
}
/*
** 这时nodeNum表示这棵树除去根层和叶子层的部分
** 劈开两半成两个三角型,其中一个三角的结点数
*/
nodeNum = fast_pow( depth - 2 ) - 1;
/* left和ritht加上nodeNum算出左右子树的结点数 */
left += nodeNum;
right += nodeNum;
/* 中序遍历总是遍历完左子树,再到根,再到右子树 */
if( x == left + 1 )
return root;
else if( x < left + 1 )
return find( x, left, depth-1, root*2 );
else
return find( x-left-1, right, depth-1, root*2+1 );
}
int main()
{
int iTom,kase;
scanf("%d",&iTom);
for( kase = 1; kase <= iTom; kase++ )
{
int n,x,depth;
long long biPow;
scanf( "%d%d", &n, &x );
for( biPow=1,depth=0; biPow < n+1; biPow <<= 1,depth++ );
printf( "Case #%d: %d\n", kase, find( x, n, depth, 1 ) );
}
return 0;
}