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 ...
随机推荐
- ACM题目————最长回文串
Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组cas ...
- ACM题目————STL练习之 懒省事的小明(优先队列)
描述 小明很想吃果子,正好果园果子熟了.在果园里,小明已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.小明决定把所有的果子合成一堆. 因为小明比较懒,为了省力气,小明开始想点子了: 每一 ...
- Python 深拷贝和浅拷贝
Python中,对象的赋值,拷贝(深/浅拷贝)之间是有差异的,如果使用的时候不注意,就可能产生意外的结果. 下面本文就通过简单的例子介绍一下这些概念之间的差别. 对象赋值 直接看一段代码: will= ...
- Java8新特性之一、时间日期API
package com.effective.common.base.date; import java.time.Instant; import java.time.LocalDate; import ...
- C#获得枚举类型的长度
enum MyEnum { Value1, Value2, } class Program { static void Main(string[] args) { var e = new MyEnum ...
- python 数据加密以及生成token和token验证
代码如下: # -*- coding: utf-8 -*- from passlib.apps import custom_app_context as pwd_context import conf ...
- Firefox浏览器设置字符编码格式
按照网上说的:工具 -> 选项 -> 内容 -> 字体&颜色 -> 高级 -> 字体编码,根本没有找到utf-8,还是把浏览器定制一下吧,看源文件的时候也可以用, ...
- 华东交通大学2016年ACM“双基”程序设计竞赛 1001
Problem Description 输入一个非负的int型整数,是奇数的话输出"ECJTU",是偶数则输出"ACM". Input 多组数据,每组数据输入一 ...
- Android ActivityThread(主线程或UI线程)简介
1. ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client ...
- 看懂UML类图和时序图
看懂UML类图和时序图 这里不会将UML的各种元素都提到,我只想讲讲类图中各个类之间的关系: 能看懂类图中各个类之间的线条.箭头代表什么意思后,也就足够应对 日常的工作和交流: 同时,我们应该能将类图 ...