POJ 2418 各种二叉排序树
题意很明确,统计各个字符串所占总串数的百分比,暴力的话肯定超时,看了书上的题解后发现这题主要是用二叉排序树来做,下面附上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 各种二叉排序树的更多相关文章
- POJ 2418 Hardwood Species(STL在map应用)
职务地址:id=2418">POJ 2418 通过这个题查了大量资料..知道了非常多曾经不知道的东西. . .. 在代码中凝视说明吧. 代码例如以下: #include <ios ...
- POJ 2418 字典树
题目链接:http://poj.org/problem?id=2418 题意:给定一堆树的名字,现在问你每一棵树[无重复]的出现的百分比,并按树名的字典序输出 思路:最简单的就是用map来写,关于字典 ...
- POJ 2418
http://poj.org/problem?id=2418 这是一个二叉树的题目,但我看了下书,还是不是特别理解会用二叉树,所以我就用其他的办法来做,结果一样AC,时间也就1700多ms,比起二叉树 ...
- poj 2418 Hardwood Species (map)
题目:http://poj.org/problem?id=2418 在poj 上交题总是有各种错误,再次感叹各个编译器. c++ AC代码,G++为超时,上代码: #include<cstdio ...
- 【gets getline的用法 char[]转化为str】poj 2418
http://poj.org/problem?id=2418 [注意] 1. 输入有空格,用 char str[maxn]; while(gets(str)){ str[]!='\0'; } 或 st ...
- [字典树] poj 2418 Hardwood Species
题目链接: id=2418">http://poj.org/problem?id=2418 Hardwood Species Time Limit: 10000MS Memory ...
- 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 ...
- 二叉搜索树 POJ 2418 Hardwood Species
题目传送门 题意:输入一大堆字符串,问字典序输出每个字符串占的百分比 分析:二叉搜索树插入,然后中序遍历就是字典序,这里root 被new出来后要指向NULL,RE好几次.这题暴力sort也是可以过的 ...
- POJ 2418 Hardwood Species
Hardwood Species Time Limit: 10000MS Memory Limit ...
随机推荐
- Xcode中设置按钮在十分钟之内禁用
btn.enabled=NO;` NSTimer * notificationTimer = [NSTimer scheduledTimerWithTimeInterval:10*60.0 targe ...
- Finding Nemo 分类: POJ 2015-07-11 10:11 10人阅读 评论(0) 收藏
Finding Nemo Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 8117 Accepted: 1883 Desc ...
- 排序练习——找出前m大的数字 分类: 排序 2015-06-08 09:33 21人阅读 评论(0) 收藏
排序练习--找出前m大的数字 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 给定n个数字,找出前m大的数字. 输入 多组输 ...
- ural 1115,搜索
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1115 题意:n个军舰,m个海岸线,各个长度给出,求n个军舰怎么组成这些海岸线. 思路很简 ...
- hdu 1205 从整体考虑
吃糖果 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submiss ...
- client/offset/srooll位置与关系
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- python学习笔记六 初识面向对象上(基础篇)
python面向对象 面向对象编程(Object-Oriented Programming )介绍 对于编程语言的初学者来讲,OOP不是一个很容易理解的编程方式,虽然大家都知道OOP的三大特性 ...
- Redis的WEB界面管理工具phpRedisAdmin
下载地址:http://down.admin5.com/php/75024.html 官方网址:https://github.com/ErikDubbelboer/phpRedisAdmin
- ios项目中引用其他项目复习
ios项目中引用其他开源项目,今天再次复习了,记个备注. 1. 将开源项目的.xcodeproj拖入项目frameworks 2. Build Phases下 Links Binary With Li ...
- iis 500 解决方法
1 打开运行,输入cmd进入到命令提示符窗口. 2 进入到C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 目录. 3 输入aspnet_regiis.exe ...