• 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

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

  • 相关阅读:
    [转]C#里 泛型Where和 new()的使用
    测试
    C#中的static、readonly与const的比较
    将字符串格式化变为两位
    在VS中对字段进行包装
    安装mysql的心得
    关于mysql数据库的乱码问题
    timestamp的两个属性:CURRENT_TIMESTAMP 和ON UPDATE CURRENT_TIMESTAMP
    解决向数据库mysql插入double数据小数点不显示问题
    JDBOOK
  • 原文地址:https://www.cnblogs.com/Newdawn/p/4284350.html
Copyright © 2020-2023  润新知