zoukankan      html  css  js  c++  java
  • POJ 2418 各种二叉排序树

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

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

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h> 
     4 
     5 typedef struct node{
     6     char name[52];
     7     struct node *lchild, *rchild;
     8     int count;
     9 }node;
    10 
    11 node *root= NULL;
    12 int n = 0;
    13 
    14 void insert(node **root, char *s){        //恶心的二级指针,以后还是用指针引用来替代吧 
    15     if(*root==NULL)    {
    16         node *p = (node*)malloc(sizeof(node));
    17         strcpy(p->name,s);
    18         p->lchild = p->rchild = NULL;
    19         p->count = 1;
    20         *root = p;        //切记这个不能漏了!! 
    21     }
    22     else {
    23         int cmp= strcmp(s,((*root)->name));
    24         if(cmp==0)    ((*root)->count)++;
    25         else if(cmp<0)    insert(&((*root)->lchild),s);
    26         else    insert(&((*root)->rchild),s);
    27     }
    28 }
    29 
    30 void midOrder(node *root){
    31     if(root!=NULL){
    32         midOrder(root->lchild);
    33         printf("%s %.4f
    ",root->name,((double)(root->count)/(double)n)*100);
    34         midOrder(root->rchild);
    35     }
    36 }
    37 
    38 int main(){
    39     char s[52];
    40     while(gets(s)){
    41         insert(&root,s);
    42         ++n;
    43     }
    44     midOrder(root);
    45     return 0;
    46 }
    View Code

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

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<algorithm>
      5 using namespace std;
      6 
      7 struct AVL
      8 {
      9     char name[32];
     10     int count;
     11     AVL *left, *right;
     12     int height;
     13 };
     14 
     15 int n = 0;
     16 
     17 int Height(AVL *p)  {   return p== NULL? -1: p->height;  }
     18 
     19 AVL* LLRotate(AVL *p)
     20 {
     21     AVL *p2= p->left;
     22     p->left= p2->right;
     23     p2->right= p;
     24     p->height= max(Height(p->left), Height(p->right))+1;
     25     p2->height= max(Height(p->left), p->height)+1;
     26     return p2;
     27 }
     28 
     29 AVL* RRRotate(AVL *p)
     30 {
     31     AVL *p2= p->right;
     32     p->right= p2->left;
     33     p2->left= p;
     34     p->height= max(Height(p->left), Height(p->right))+1;
     35     p2->height= max(p->height, Height(p2->right))+1;
     36     return p2;
     37 }
     38 
     39 AVL* LRRotate(AVL *p)
     40 {
     41     p->left= RRRotate(p->left);
     42     return LLRotate(p);
     43 }
     44 
     45 AVL* RLRotate(AVL *p)
     46 {
     47     p->right= LLRotate(p->right);
     48     return RRRotate(p);
     49 }
     50 
     51 AVL* Insert(const char *s, AVL *p)
     52 {
     53     if(p==NULL){
     54         p= (AVL*)malloc(sizeof(AVL));
     55         strcpy(p->name, s);
     56         p->left= p->right= NULL;
     57         p->height= 0;
     58         p->count= 1;
     59     }
     60     else {
     61         int cmp= strcmp(s,p->name);
     62         if(cmp==0)  ++(p->count);
     63         else if(cmp<0){
     64             p->left= Insert(s,p->left);
     65             if(Height(p->left) - Height(p->right) == 2){
     66                 if(strcmp(s,p->left->name)<0)
     67                     p= LLRotate(p);
     68                 else    p= LRRotate(p);
     69             }
     70         }
     71         else if(cmp>0){
     72             p->right= Insert(s,p->right);
     73             if(Height(p->right) - Height(p->left) == 2){
     74                 if(strcmp(s,p->right->name)>0)
     75                     p= RRRotate(p);
     76                 else    p= RLRotate(p);
     77             }
     78         }
     79     }
     80     p->height= max(Height(p->left), Height(p->right))+1;
     81     return p;
     82 }
     83 
     84 void midOrder(AVL* p)
     85 {
     86     if(p){
     87         midOrder(p->left);
     88         printf("%s %.4f
    ",p->name,double(p->count)/n*100);
     89         midOrder(p->right);
     90     }
     91 }
     92 
     93 int main()
     94 {
     95     AVL *root= NULL;
     96     char s[32];
     97     while(gets(s)){
     98         root= Insert(s,root);
     99         ++n;
    100     }
    101     midOrder(root);
    102     return 0;
    103 }
    View Code

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

     1 #include<cstdio>
     2 #include<map>
     3 #include<iterator>
     4 #include<string>
     5 #include<iostream>
     6 using namespace std;
     7 
     8 int main()
     9 {
    10     int n =0;
    11     string s;
    12     map<string,int> tree;
    13     while(getline(cin,s)){        //直接用cin的话空格会读不进去
    14         ++tree[s];
    15         ++n;
    16     }
    17     map<string,int>::iterator it;
    18     for(it=tree.begin(); it!=tree.end(); ++it){
    19     //    cout<<it->first;
    20         printf("%s %.4f
    ",it->first.c_str(), it->second*100.0/n);
    21     }
    22 }
    View Code

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

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<ctime>
      4 #include<cstring>
      5 #include<algorithm>
      6 using namespace std;
      7 const int maxn= 32;
      8 
      9 struct node
     10 {
     11     node *ch[2];    //左右子树
     12     int r;      //优先级
     13     int s;      //结点总数
     14     char name[maxn];    //结点名称
     15     int num;        //结点出现次数
     16     node(char s2[])
     17     {
     18         strcpy(name,s2);
     19         num= 1;
     20         ch[0]= ch[1]= NULL;
     21         r= rand();
     22         s= 1;
     23     }
     24     bool operator <(const node &n2) const {  return r < n2.r;  }
     25     int cmp(char s2[]) const
     26     {
     27         int d= strcmp(name,s2);
     28         if(!d)  return -1;
     29         return  d<0? 0:1;
     30     }
     31     void maintain()
     32     {
     33         s= 1;
     34         if(ch[0]!=NULL)  s+= ch[0]->s;
     35         if(ch[1]!=NULL)  s+= ch[1]->s;
     36     }
     37 };
     38 
     39 node *treap= NULL;
     40 int n= 0;
     41 
     42 void rotate(node* &p, int d)
     43 {
     44     node* k= p->ch[d^1];
     45     p->ch[d^1]= k->ch[d];
     46     k->ch[d]= p;
     47     p->maintain();
     48     k->maintain();
     49     p= k;
     50 }
     51 
     52 void insert(node* &p, char s2[])
     53 {
     54     if(p==NULL)  p= new node(s2);
     55     else {
     56         int d= strcmp(s2,p->name);
     57         if(!d)  p->num++;
     58         else {
     59             d= d<0? 0:1;
     60             insert(p->ch[d],s2);
     61             if(p->ch[d]->r > p->r)  rotate(p,d^1);
     62         }
     63     }
     64     p->maintain();
     65 }
     66 
     67 void remove(node* &p, char s2[])
     68 {
     69     if(p==NULL){
     70         puts("该结点不存在,无法删除...");
     71         return ;
     72     }
     73     int d= p->cmp(s2);
     74     if(d==-1){
     75         node *u= p;
     76         if(p->ch[0]==NULL)  p= p->ch[1];
     77         else if(p->ch[1]==NULL)  p= p->ch[0];
     78         else {
     79             int d2= (p->ch[0]->r > p->ch[1]->r ? 1: 0);
     80             rotate(p,d2);
     81             remove(p->ch[d2],s2);
     82         }
     83         delete u;
     84     }
     85     else    remove(p->ch[d],s2);
     86     if(p!=NULL)   p->maintain();
     87 }
     88 
     89 bool find(node* p, char s2[])
     90 {
     91     while(p){
     92         int d= p->cmp(s2);
     93         if(d==-1)   return 1;
     94         else   p= p->ch[d];
     95     }
     96     return 0;
     97 }
     98 
     99 void midOrder(node *p)
    100 {
    101     if(p){
    102         midOrder(p->ch[0]);
    103         printf("%s %.4f
    ",p->name,double(p->num)/n*100);
    104         midOrder(p->ch[1]);
    105     }
    106 }
    107 
    108 int main()
    109 {
    110     char s[32];
    111     srand(time(NULL));
    112     while(gets(s)){
    113         insert(treap,s);
    114         ++n;
    115     }
    116     midOrder(treap);
    117     return 0;
    118 }
    View Code

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

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<string>
     4 #include<algorithm>
     5 #include<iostream>
     6 #include<cstdlib>
     7 using namespace std;
     8 string str[1000006];
     9 
    10 //这种方法可能相对会慢一点:2610ms,27640K,其余几种都是1000+ms
    11 
    12 int main()
    13 {
    14     int i= 0;
    15     while(getline(cin,str[i++])) ;
    16     sort(str,str+i);
    17 
    18     //因为最后的换行符也会读进去,所以ed要从1开始,而总数量是i-1而不是i
    19     int st,ed= 1;
    20     while(ed<i){
    21         st= lower_bound(str+ed, str+i, str[ed]) - str;
    22         ed= upper_bound(str+ed, str+i, str[ed]) - str;
    23         printf("%s %.4f
    ",str[st].c_str(), double(ed-st)/(i-1)*100);
    24     }
    25     return 0;
    26 }
    View Code

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

  • 相关阅读:
    HDU 5791 Two (DP)
    POJ 1088 滑雪 (DPor记忆化搜索)
    LightOJ 1011
    POJ 1787 Charlie's Change (多重背包 带结果组成)
    HDU 5550 Game Rooms (ccpc2015 K)(dp)
    HDU 5542 The Battle of Chibi (ccpc 南阳 C)(DP 树状数组 离散化)
    HDU 5543 Pick The Sticks (01背包)
    HDU 5546 Ancient Go (ccpc2015南阳G)
    NB-IoT的DRX、eDRX、PSM三个模式 (转载,描述的简单易懂)
    MQTT 嵌入式端通讯协议解析(转)
  • 原文地址:https://www.cnblogs.com/Newdawn/p/4284350.html
Copyright © 2011-2022 走看看