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 ...
随机推荐
- 【转】在Eclipse中配置tomcat
转载地址: http://kin111.blog.51cto.com/738881/163096 为了在Eclipse中进行struts2的测试,才发现自己机器上的Eclipse没有集成Tomcat, ...
- HashMap, HashTable, CurrentHashMap的区别
转载:http://www.jianshu.com/p/c00308c32de4 HashMap vs ConcurrentHashMap 引入ConcurrentHashMap是为了在同步集合Has ...
- jQuery 一些小技巧
1. 返回顶部按钮 可以利用 animate 和 scrollTop 来实现返回顶部的动画,而不需要使用其他插件. // Back to top ...
- 2016年11月15日 星期二 --出埃及记 Exodus 20:6
2016年11月15日 星期二 --出埃及记 Exodus 20:6 but showing love to a thousand of those who love me and keep my c ...
- sql通用分页自定义表条件存储过程
create PROCEDURE PrcTestByPage ( @tablename varchar(50), @selectfilter varchar(100), @orderbyfilter ...
- 数据库SQL语句练习题5--9
5. 查询Score表中成绩为85,86或88的记录. ,,) 6. 查询Student表中“95031”班或性别为“女”的同学记录. ' or ssex = '女' 7. 以Class降序查询Stu ...
- Cheatsheet: 2013 08.01 ~ 08.13
Mobile Objective C Blocks: Summary, Syntax & Best Practices Android SDK: Create an Arithmetic Ga ...
- 手把手教你把Vim改装成一个IDE编程环境(图文)
http://blog.csdn.net/wooin/article/details/1858917
- MySQL用户名和密码问题
MySQL使用脚本的方法: source d:\datafilename.sql # mysql -uroot -p Enter password: ERROR 1045 (28000): Acces ...
- oracle数据库中提供的5种约束
约束作用:用来保持数据的完整性,防止无效数据进入到数据库中.oracle数据库中提供的5种约束,都是限定某个列或者列的组合的.1.主键约束(PRIMARY KEY):在一个表中能唯一的标识一行.主键可 ...