题目大意:
阔叶林是一种植物群落,其中的树木都具有叶子面子很大这一共同特征,多结坚果,冬天会进入休眠状态。美国的温度和气候创造了近百种阔叶物种,如橡树、枫树、樱桃树等等,阔叶树几乎占全美树种的40%左右。另一方面,针叶树(拉丁语称为”锥轴树“,因为其叶子是锥形针状的)在美国也随处可见,如雪松、冷杉、铁杉、红杉等。一般针叶树在家里被用作装饰性的木材。
现自然资源部门使用卫星成像技术,在每一天都编制了一张图像清单,记录了一定范围内的每一颗树,先需要你编程计算每一天记录的树种的”人口结构“。
有多个测例(测例无上限),每个测例中都会给出一张树的清单(由卫星拍摄,以树种名称给出),每一颗树占一行,树名不超过30个字符,其中树会重复出现,不会超过10,000个树种,也不会超过1,000,000棵树,对于每个测例都需要按字典升序给出每种树的树名和其占总数的百分比(截断至4位小数),每种树各占一行。
BST:
注释代码:
/*
* Problem ID : POJ 2418 Hardwood Species
* Author : Lirx.t.Una
* Language : C++
* Run Time : 1110 ms
* Run Memory : 312 KB
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
//maximum length of species' name,
//物种名称的最大长度
//最后一位留给空字符
//30 + 1
#define MAXNAMELEN 31
struct Node;
typedef struct Node * PtNode;
typedef struct Node * Tree;
struct Node {//二叉搜索树的结点
char name[MAXNAMELEN];
Tree lft;
Tree rht;
int cnt;//count,记录该物种出现过多少次
};
int n;//树的总数
void
insert( Tree &tree, char *name ) {//向BST中插入一个结点
//传的是Node指针的引用,这样可以对上层递归函数传进来的
//father_node->lft/rht进行修改了
if ( !tree ) {//若数为空就代表已经递归到了底部(叶子结点的下面一层)
//此时可以插入该结点了
tree = (PtNode)malloc( sizeof(Node) );
strcpy( tree->name, name );
tree->lft = NULL;
tree->rht = NULL;
tree->cnt = 1;
return ;
}
int cmp;
cmp = strcmp(tree->name, name);
if ( !cmp ) {//若刚好就是当前结点所代表的物种
//就将该物种的数量加1
tree->cnt++;
return ;
}
if ( cmp < 0 )//若字母顺序小于当前结点所表示的物种就
//插入到其左子树中
insert( tree->rht, name );
else//否则就插入其右子树
insert( tree->lft, name );
}
void
travel(Tree tree) {//中序遍历
if (tree) {//先左后右
travel( tree->lft );
printf("%s %.4f\n", tree->name, (double)tree->cnt / (double)n * 100.0);
travel( tree->rht );
}
}
int
main() {
char name[MAXNAMELEN];
Tree tree;
tree = NULL;
n = 0;
while ( gets(name) ) {
insert( tree, name );
n++;
}
travel(tree);
return 0;
}
无注释代码:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAXNAMELEN 31
struct Node;
typedef struct Node * PtNode;
typedef struct Node * Tree;
struct Node {
char name[MAXNAMELEN];
Tree lft;
Tree rht;
int cnt;
};
int n;
void
insert( Tree &tree, char *name ) {
if ( !tree ) {
tree = (PtNode)malloc( sizeof(Node) );
strcpy( tree->name, name );
tree->lft = NULL;
tree->rht = NULL;
tree->cnt = 1;
return ;
}
int cmp;
cmp = strcmp(tree->name, name);
if ( !cmp ) {
tree->cnt++;
return ;
}
if ( cmp < 0 )
insert( tree->rht, name );
else
insert( tree->lft, name );
}
void
travel(Tree tree) {
if (tree) {
travel( tree->lft );
printf("%s %.4f\n", tree->name, (double)tree->cnt / (double)n * 100.0);
travel( tree->rht );
}
}
int
main() {
char name[MAXNAMELEN];
Tree tree;
tree = NULL;
n = 0;
while ( gets(name) ) {
insert( tree, name );
n++;
}
travel(tree);
return 0;
}
AVL:
注释代码:
/*
* Problem ID : POJ 2418 Hardwood Species
* Author : Lirx.t.Una
* Language : GCC
* Run Time : 1329 ms
* Run Memory : 512 KB
*/
#pragma GCC optimize("O2")
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAXNAMELEN 31
struct Node;
typedef struct Node * PtNode;
typedef struct Node * Tree;
struct Node {
char name[MAXNAMELEN];
Tree lft;
Tree rht;
int h;//每个AVL树结点还需维护
//该结点所代表的数的高度
//一边对后面左右子树高度的调整
//以及旋转带来依据
int cnt;
};
int n;
int
Height(Tree tree) {//空结点高度为-1,
//单节点高度为0
if ( !tree )
return -1;
return tree->h;
}
int
MaxHRL(Tree tree) {//maximum height in left tree and right tree,
//计算左右子树两者较高的高度
int hl, hr;//height of left tree and right tree
hl = Height( tree->lft );
hr = Height( tree->rht );
return hl > hr ? hl : hr;
}
Tree
RotL(Tree k2) {//Rotation in left,左旋转
Tree k1;
k1 = k2->lft;
k2->lft = k1->rht;
k1->rht = k2;
//旋转后,由于k2的左子树改变
//并且k2成为了k1的子树
//因此需要先更新k2的高度
//然后再更新k1的高度
k2->h = MaxHRL(k2) + 1;
k1->h = MaxHRL(k1) + 1;
return k1;
}
Tree
RotR(Tree k2) {//Rotation in right
Tree k1;
k1 = k2->rht;
k2->rht = k1->lft;
k1->lft = k2;
k2->h = MaxHRL(k2) + 1;
k1->h = MaxHRL(k1) + 1;
return k1;
}
Tree
RotLR(Tree t) {//Rotation first in left,then in right,
//双旋转,先对t的右子树左转,再对t右转
t->rht = RotL( t->rht );
return RotR(t);
}
Tree
RotRL(Tree t) {//Rotation first in right, then in left
t->lft = RotR( t->lft );
return RotL(t);
}
Tree
Insert( Tree tree, char *name ) {//向AVL中插入结点
if ( !tree ) {
PtNode node;
node = (PtNode)malloc( sizeof( struct Node ) );
strcpy( node->name, name );
node->lft = NULL;
node->rht = NULL;
node->h = 0;//单结点树高度为0
node->cnt = 1;
return node;
}
int cmp;
cmp = strcmp( name, tree->name );
if ( !cmp ) {
tree->cnt++;
return tree;
}
if ( cmp < 0 ) {//插入物种字母顺序小于当前结点则插入到左子树中
tree->lft = Insert( tree->lft, name );
//由于插入后左子树是AVL平衡的,但是不能保证tree也是平衡的(因为这是递归插入)
if ( 2 == Height( tree->lft ) - Height( tree->rht ) )//若不平衡
if ( strcmp( name, tree->lft->name ) < 0 )//插入物种字母小于左子树,
//这就意味着tree左偏
return RotL(tree);
else//否则就是大于右子树
//不可能出现等于,因为等于就意味着没有插入结点,由于原来是AVL平衡的
//既然没有插入结点就意味着现在也是平衡的,因此不可能会出现不平衡的情况
return RotRL(tree);
}
else {//插入到右子树的情景是相同的
tree->rht = Insert( tree->rht, name );
if ( 2 == Height( tree->rht ) - Height( tree->lft ) )
if ( strcmp( name, tree->rht->name ) > 0 )
return RotR(tree);
else
return RotLR(tree);
}
//由于进行旋转时旋转函数已经将tree的高度更新了
//但是如果插入左右子树后没出现失衡,那也就是说没有进入旋转函数过
//因此tree的高度也就没有更新过
//因此这里需要对tree的高度进行更新
tree->h = MaxHRL(tree) + 1;
return tree;
}
void
Travel(Tree tree) {
if (tree) {
Travel( tree->lft );
printf("%s %.4f\n", tree->name, (double)tree->cnt / (double)n * 100.0);
Travel( tree->rht );
}
}
int
main() {
char name[MAXNAMELEN];
Tree tree;
tree = NULL;
n = 0;
while ( gets(name) ) {
tree = Insert( tree, name );
n++;
}
Travel(tree);
return 0;
}
无注释代码:
#pragma GCC optimize("O2")
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAXNAMELEN 31
struct Node;
typedef struct Node * PtNode;
typedef struct Node * Tree;
struct Node {
char name[MAXNAMELEN];
Tree lft;
Tree rht;
int h;
int cnt;
};
int n;
int
Height(Tree tree) {
if ( !tree )
return -1;
return tree->h;
}
int
MaxHRL(Tree tree) {
int hl, hr;
hl = Height( tree->lft );
hr = Height( tree->rht );
return hl > hr ? hl : hr;
}
Tree
RotL(Tree k2) {
Tree k1;
k1 = k2->lft;
k2->lft = k1->rht;
k1->rht = k2;
k2->h = MaxHRL(k2) + 1;
k1->h = MaxHRL(k1) + 1;
return k1;
}
Tree
RotR(Tree k2) {
Tree k1;
k1 = k2->rht;
k2->rht = k1->lft;
k1->lft = k2;
k2->h = MaxHRL(k2) + 1;
k1->h = MaxHRL(k1) + 1;
return k1;
}
Tree
RotLR(Tree t) {
t->rht = RotL( t->rht );
return RotR(t);
}
Tree
RotRL(Tree t) {
t->lft = RotR( t->lft );
return RotL(t);
}
Tree
Insert( Tree tree, char *name ) {
if ( !tree ) {
PtNode node;
node = (PtNode)malloc( sizeof( struct Node ) );
strcpy( node->name, name );
node->lft = NULL;
node->rht = NULL;
node->h = 0;
node->cnt = 1;
return node;
}
int cmp;
cmp = strcmp( name, tree->name );
if ( !cmp ) {
tree->cnt++;
return tree;
}
if ( cmp < 0 ) {
tree->lft = Insert( tree->lft, name );
if ( 2 == Height( tree->lft ) - Height( tree->rht ) )
if ( strcmp( name, tree->lft->name ) < 0 )
return RotL(tree);
else
return RotRL(tree);
}
else {
tree->rht = Insert( tree->rht, name );
if ( 2 == Height( tree->rht ) - Height( tree->lft ) )
if ( strcmp( name, tree->rht->name ) > 0 )
return RotR(tree);
else
return RotLR(tree);
}
tree->h = MaxHRL(tree) + 1;
return tree;
}
void
Travel(Tree tree) {
if (tree) {
Travel( tree->lft );
printf("%s %.4f\n", tree->name, (double)tree->cnt / (double)n * 100.0);
Travel( tree->rht );
}
}
int
main() {
char name[MAXNAMELEN];
Tree tree;
tree = NULL;
n = 0;
while ( gets(name) ) {
tree = Insert( tree, name );
n++;
}
Travel(tree);
return 0;
}
单词解释:
hardwood:n, 阔叶树,硬木
hardwoods:n, 阔叶林
species:n, 物种,种类
botanical:n, 植物学的
broad:adj, 宽阔的
nut:n, 坚果
dormant:adj, 休眠的
generally:adv, 通常,一般
climate:n, 气候
biological:adj, 生物学的
characteristic:n, 特征
oak:n, 橡树
maple:n, 枫树
cherry:n, 樱桃树
softwood:n, 针叶树,软木
softwoods:n, 针叶林
conifer:n, 针叶树
cone:n, 圆锥体
bearing:n, 轴承
cone bearing:n, 圆锥轴承
needle:n, 针
widely available:广泛可见的,广泛可接触的
cedar:n, 雪松
fir:n, 冷杉
hemlock:n, 铁杉
pine:n, 松树
redwood:n, 红杉
spruce:n, 云杉
cypress:n, 柏树
primarily:adv, 主要地,首先
lumber:n, 木材
structural:adj, 建筑的,结构的
decorative:adj, 装潢用的,装饰性的
application:n, 用途,应用,应用程序
satellite:n, 人造卫星
imaging:n, 成像
satellite imaging technology:n, 卫星成像技术
resource:n, 资源(指自然资源),也可指人力资源
inventory:n, 详细目录,存货清单
compile:vt, 编制,编译
fraction:n, 部分,小部分
alphabetical:adj, 按字母顺序的
percentage:n, 百分比