题意很明确,统计各个字符串所占总串数的百分比,暴力的话肯定超时,看了书上的题解后发现这题主要是用二叉排序树来做,下面附上n种树的代码。

  简单的二叉排序树,不作任何优化(C语言版的):

 #include<stdio.h>
#include<string.h>
#include<stdlib.h> typedef struct node{
char name[];
struct node *lchild, *rchild;
int count;
}node; node *root= NULL;
int n = ; void insert(node **root, char *s){ //恶心的二级指针,以后还是用指针引用来替代吧
if(*root==NULL) {
node *p = (node*)malloc(sizeof(node));
strcpy(p->name,s);
p->lchild = p->rchild = NULL;
p->count = ;
*root = p; //切记这个不能漏了!!
}
else {
int cmp= strcmp(s,((*root)->name));
if(cmp==) ((*root)->count)++;
else if(cmp<) insert(&((*root)->lchild),s);
else insert(&((*root)->rchild),s);
}
} void midOrder(node *root){
if(root!=NULL){
midOrder(root->lchild);
printf("%s %.4f\n",root->name,((double)(root->count)/(double)n)*);
midOrder(root->rchild);
}
} int main(){
char s[];
while(gets(s)){
insert(&root,s);
++n;
}
midOrder(root);
return ;
}

  然后这是AVL(平衡二叉树),目前我只会插入的平衡,删除还不会,代码量还挺多的:

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std; struct AVL
{
char name[];
int count;
AVL *left, *right;
int height;
}; int n = ; int Height(AVL *p) { return p== NULL? -: p->height; } AVL* LLRotate(AVL *p)
{
AVL *p2= p->left;
p->left= p2->right;
p2->right= p;
p->height= max(Height(p->left), Height(p->right))+;
p2->height= max(Height(p->left), p->height)+;
return p2;
} AVL* RRRotate(AVL *p)
{
AVL *p2= p->right;
p->right= p2->left;
p2->left= p;
p->height= max(Height(p->left), Height(p->right))+;
p2->height= max(p->height, Height(p2->right))+;
return p2;
} AVL* LRRotate(AVL *p)
{
p->left= RRRotate(p->left);
return LLRotate(p);
} AVL* RLRotate(AVL *p)
{
p->right= LLRotate(p->right);
return RRRotate(p);
} AVL* Insert(const char *s, AVL *p)
{
if(p==NULL){
p= (AVL*)malloc(sizeof(AVL));
strcpy(p->name, s);
p->left= p->right= NULL;
p->height= ;
p->count= ;
}
else {
int cmp= strcmp(s,p->name);
if(cmp==) ++(p->count);
else if(cmp<){
p->left= Insert(s,p->left);
if(Height(p->left) - Height(p->right) == ){
if(strcmp(s,p->left->name)<)
p= LLRotate(p);
else p= LRRotate(p);
}
}
else if(cmp>){
p->right= Insert(s,p->right);
if(Height(p->right) - Height(p->left) == ){
if(strcmp(s,p->right->name)>)
p= RRRotate(p);
else p= RLRotate(p);
}
}
}
p->height= max(Height(p->left), Height(p->right))+;
return p;
} void midOrder(AVL* p)
{
if(p){
midOrder(p->left);
printf("%s %.4f\n",p->name,double(p->count)/n*);
midOrder(p->right);
}
} int main()
{
AVL *root= NULL;
char s[];
while(gets(s)){
root= Insert(s,root);
++n;
}
midOrder(root);
return ;
}

  以上两者都参考了书上的代码模板,想简单一点的话可以直接用STL中封装的很好的 map(红黑树):

 #include<cstdio>
#include<map>
#include<iterator>
#include<string>
#include<iostream>
using namespace std; int main()
{
int n =;
string s;
map<string,int> tree;
while(getline(cin,s)){ //直接用cin的话空格会读不进去
++tree[s];
++n;
}
map<string,int>::iterator it;
for(it=tree.begin(); it!=tree.end(); ++it){
// cout<<it->first;
printf("%s %.4f\n",it->first.c_str(), it->second*100.0/n);
}
}

  Treap树堆,通过随机确定的优先级来平衡二叉排序树,参考了刘汝佳大白书上的模板,旋转处的小技巧确实很巧妙:(如果单纯针对本题的话 remove 和 find 函数都可以不要,代码比AVL短一些)

 #include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn= ; struct node
{
node *ch[]; //左右子树
int r; //优先级
int s; //结点总数
char name[maxn]; //结点名称
int num; //结点出现次数
node(char s2[])
{
strcpy(name,s2);
num= ;
ch[]= ch[]= NULL;
r= rand();
s= ;
}
bool operator <(const node &n2) const { return r < n2.r; }
int cmp(char s2[]) const
{
int d= strcmp(name,s2);
if(!d) return -;
return d<? :;
}
void maintain()
{
s= ;
if(ch[]!=NULL) s+= ch[]->s;
if(ch[]!=NULL) s+= ch[]->s;
}
}; node *treap= NULL;
int n= ; void rotate(node* &p, int d)
{
node* k= p->ch[d^];
p->ch[d^]= k->ch[d];
k->ch[d]= p;
p->maintain();
k->maintain();
p= k;
} void insert(node* &p, char s2[])
{
if(p==NULL) p= new node(s2);
else {
int d= strcmp(s2,p->name);
if(!d) p->num++;
else {
d= d<? :;
insert(p->ch[d],s2);
if(p->ch[d]->r > p->r) rotate(p,d^);
}
}
p->maintain();
} void remove(node* &p, char s2[])
{
if(p==NULL){
puts("该结点不存在,无法删除...");
return ;
}
int d= p->cmp(s2);
if(d==-){
node *u= p;
if(p->ch[]==NULL) p= p->ch[];
else if(p->ch[]==NULL) p= p->ch[];
else {
int d2= (p->ch[]->r > p->ch[]->r ? : );
rotate(p,d2);
remove(p->ch[d2],s2);
}
delete u;
}
else remove(p->ch[d],s2);
if(p!=NULL) p->maintain();
} bool find(node* p, char s2[])
{
while(p){
int d= p->cmp(s2);
if(d==-) return ;
else p= p->ch[d];
}
return ;
} void midOrder(node *p)
{
if(p){
midOrder(p->ch[]);
printf("%s %.4f\n",p->name,double(p->num)/n*);
midOrder(p->ch[]);
}
} int main()
{
char s[];
srand(time(NULL));
while(gets(s)){
insert(treap,s);
++n;
}
midOrder(treap);
return ;
}

  实质上,这题也可以不用树来做,读入所有字符串并排序后,通过 lower_bound 和 upper_bound 函数的差值来依次求出每个字串的数量/百分比(这是从《挑战》书上学到的):

 #include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<cstdlib>
using namespace std;
string str[]; //这种方法可能相对会慢一点:2610ms,27640K,其余几种都是1000+ms int main()
{
int i= ;
while(getline(cin,str[i++])) ;
sort(str,str+i); //因为最后的换行符也会读进去,所以ed要从1开始,而总数量是i-1而不是i
int st,ed= ;
while(ed<i){
st= lower_bound(str+ed, str+i, str[ed]) - str;
ed= upper_bound(str+ed, str+i, str[ed]) - str;
printf("%s %.4f\n",str[st].c_str(), double(ed-st)/(i-)*);
}
return ;
}

  这两天稍微看了看数据结构,感觉还是挺费脑子的,各种变式的二叉排序树,很容易混淆或者记不住,看来要加深理解才能熟练运用。

POJ 2418 各种二叉排序树的更多相关文章

  1. POJ 2418 Hardwood Species(STL在map应用)

    职务地址:id=2418">POJ 2418 通过这个题查了大量资料..知道了非常多曾经不知道的东西. . .. 在代码中凝视说明吧. 代码例如以下: #include <ios ...

  2. POJ 2418 字典树

    题目链接:http://poj.org/problem?id=2418 题意:给定一堆树的名字,现在问你每一棵树[无重复]的出现的百分比,并按树名的字典序输出 思路:最简单的就是用map来写,关于字典 ...

  3. POJ 2418

    http://poj.org/problem?id=2418 这是一个二叉树的题目,但我看了下书,还是不是特别理解会用二叉树,所以我就用其他的办法来做,结果一样AC,时间也就1700多ms,比起二叉树 ...

  4. poj 2418 Hardwood Species (map)

    题目:http://poj.org/problem?id=2418 在poj 上交题总是有各种错误,再次感叹各个编译器. c++ AC代码,G++为超时,上代码: #include<cstdio ...

  5. 【gets getline的用法 char[]转化为str】poj 2418

    http://poj.org/problem?id=2418 [注意] 1. 输入有空格,用 char str[maxn]; while(gets(str)){ str[]!='\0'; } 或 st ...

  6. [字典树] poj 2418 Hardwood Species

    题目链接: id=2418">http://poj.org/problem?id=2418 Hardwood Species Time Limit: 10000MS   Memory ...

  7. POJ 2418 ,ZOJ 1899 Hardwood Species - from lanshui_Yang

    Description Hardwoods are the botanical group of trees that have broad leaves, produce a fruit or nu ...

  8. 二叉搜索树 POJ 2418 Hardwood Species

    题目传送门 题意:输入一大堆字符串,问字典序输出每个字符串占的百分比 分析:二叉搜索树插入,然后中序遍历就是字典序,这里root 被new出来后要指向NULL,RE好几次.这题暴力sort也是可以过的 ...

  9. POJ 2418 Hardwood Species

                                                     Hardwood Species Time Limit: 10000MS   Memory Limit ...

随机推荐

  1. 每日一九度之 题目1031:xxx定律

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6870 解决:4302 题目描述:     对于一个数n,如果是偶数,就把n砍掉一半:如果是奇数,把n变成 3*n+ 1后砍掉一半,直到该数 ...

  2. Communication System(dp)

    Communication System Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 25006 Accepted: 8925 ...

  3. PL/SQL注册码

    code:j6stndb9tk72xfbhbqczcdqnjd8lyj466n number:882851 ps:xs374ca

  4. laravel框架总结(二) -- blade模板引擎

    ## 1.基本用法 ##情形1 $name = laravel5 <div class="title"> {{$name}} {{$name}}</div> ...

  5. Annotation实战【自定义AbstractProcessor】

    前言 在使用Java的过程中,每个开发人员都接触过@Override, @Deprecated等等各式各样的注解,这些东西是java最基础的一些原生定义好的annotation.本文通过一个实例演示如 ...

  6. CodeForces 490C Hacking Cypher

    Hacking Cypher Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Sub ...

  7. 【转载】理解C语言中的关键字extern

    原文:理解C语言中的关键字extern 最近写了一段C程序,编译时出现变量重复定义的错误,自己查看没发现错误.使用Google发现,自己对extern理解不透彻,我搜到了这篇文章,写得不错.我拙劣的翻 ...

  8. java读取文件多种方法

    1.按字节读取文件内容2.按字符读取文件内容3.按行读取文件内容 4.随机读取文件内容 public class ReadFromFile {     /**      * 以字节为单位读取文件,常用 ...

  9. 精通正则表达式(第三版)——Mastering Regular Expressions,3rd Edition——读书笔记1

    基础知识介绍: 子表达式匹配 环视 引号内的字符串:"(^")*" 12小时制:(1[0123]|[1-9]):[0-5][0-9]*(am|pm) 24小时制:(([0 ...

  10. [SAP ABAP开发技术总结]OLE

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...