您的位置:首页 > 其它

poj 2309 BST (^ ^)

2010-12-29 23:46 267 查看
这是个很好的题目呢~~画图画了半天 = =、、



这是一棵完全二叉查找树 = =。。。



给你一个节点n,求n的子树中最小,最大值。



放图,得睡了,明天继续写。







继续~





看下面的图,找规律。可以发现。每个节点的父节点的父节点的。。。总之,总有一个是2的幂次。等于说,这些所有的除了2的幂次的数,都是2幂次数的右子树上的一个节点。而且可以发现,奇数都是叶节点,而且所有的叶节点都是奇数。

我的想法就是,给你一个数n,找比n小的最近的2的幂次的数为root,如果n本身就是2的幂次,它自己就是root。然后开始从root往下找,找到与n相等的地方,比如查找28,先找到16,是2^4,count = 4-1 = 3。那么16就需要增加2^(count-1)去寻找。如果16+(2^(count-1)) > n 就16+ (2^(count-1)) ,反之,16-(2^(count-1)) ,就是查找到n。count每次减1,直到找到n。



root = 2^4 = 16;

比如 root + 8 < 28, root = 16+8 = 24;

root + 4 == 28;找到n跳出。

然后根据得到的count继续忘下找,相当于找到28忘子节点需要加或者减的数。然后一直找到count 为0。















#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
	int ncases,n,i;
	scanf("%d",&ncases);
	while( ncases-- )
	{
		scanf("%d",&n);
		if( n%2 == 1 )
		{
			printf("%d %d/n",n,n);//经画图,以及种种考虑 = =。。。奇数全在最后一行 
			continue;
		}
		int tmp = n,count = 0;
		while( tmp != 0 )			//查找比n小的最近的2^n的数 
		{
			tmp /= 2;
			count++;
		}
		count -- ;
		int flag = 0;
		if( (1<<count) == n ) 		// 如果本身就是2的幂次,就标记下~下面有用。。 
			flag = 1;
		int root = (1 << count);   //就是这个root啦~~ 
		for(i=count-1; i>=0; i--)	// 从root开始往下查找。经种种现象表示,n一定是比它小的它最近的2的幂次的数的子节点。 
		{
			if( n > root )
				root += (1<<i);
			if( n == root )
				break;
			if( n < root )
				root -= (1<<i);
		}
		if( flag == 1 )  // 如果本身就是2的幂次,那么少加一次。。 
			i++;
		int min,max;
		min = max = n;
		for(int k=i-1; k>=0; k--) // 作为根节点,往左子树左边和右子树右边找最小和最大值。 
		{
			min -= (1<<k);
			max += (1<<k);
		}
		printf("%d %d/n",min,max);
	}
return 0;	
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: