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 ...
随机推荐
- sprint2(第七天)
因为GitHub有时候我们更新不上,然后浪费很多时间,所以我们决定几天上传一次,而且有时候我们的功能在做,不一定一天能做完,所以几天做完一个模块再一起上传比较好.昨天的燃尽图有点错,有个功能做了没有把 ...
- easyui tab 关闭
<div id="mm" class="easyui-menu" style="width:150px;"> &l ...
- R2D2 and Droid Army(多棵线段树)
R2D2 and Droid Army time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- Poj(2679),SPFA,邻接表(主流写法)
题目链接:http://poj.org/problem?id=3268 题意: 有编号为1-N的牛,它们之间存在一些单向的路径.给定一头牛的编号,其他牛要去拜访它并且拜访完之后要返回自己原来的位置,求 ...
- Sublime Text shift+ctrl妙用、Sublime Text快捷组合键大全
Package Control 安装方法 首先通过快捷键 ctrl+` 或者 View > Show Console 打开控制台,然后粘贴相应的 Python 安装代码. 1 :按住shift+ ...
- 2016年6月25日 星期六 --出埃及记 Exodus 14:22
2016年6月25日 星期六 --出埃及记 Exodus 14:22 and the Israelites went through the sea on dry ground, with a wal ...
- centos 001
CentOS6.5中修改yum源 在自己安装的CentOS6.5中使用yum安装软件,总是提示404错误信息,百度后发现原来要设置yum源. 在安装完CentOS后一般需要修改yum源,才能够在安装更 ...
- config文件 反射方法
string testPropertyName = "MainFormText"; Properties.Settings setting = Properties.Settin ...
- Java CSV操作(导出和导入)
Java CSV操作(导出和导入) CSV是逗号分隔文件(Comma Separated Values)的首字母英文缩写,是一种用来存储数据的纯文本格式,通常用于电子表格或数据库软件.在 CSV文件 ...
- Python3基础 for循环 遍历并输出一个字符串的列表
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...