binary search tree(bst)

什么是bst?

bst树,通常称为二叉搜索树,又叫二叉排序树,bst是一种特殊的二叉树结构,也是一种常见的数据结构类型,其中,bst很明显的特性是根节点大于左子树的节点小于右子树的节点,并且满足其子树又是一颗独立的bst树。

二叉搜索树的应用基本有名次树(树堆),AVL(平衡二叉树),splay树,sbt树和恶名昭著红黑树

bst的基本操作有建树(插入),删除,查找,其中删除有较为特殊,分为两种情况,其余细节请自行baidu或者查书

这里简单说说bst的几个细节小性质:

1.建树如果给定序列,则形成的bst是唯一的,最坏情况是单枝树,最好情况是一颗完美二叉树(满二叉树)

2.在删除bst节点的时候,如果是删除非叶节点,一般是找左子树的最大节点或者是右子树的最小节点,

换句话说,就是左子树的最右节点和右子树的最左节点(请思考是为甚么)

3.bst的inorder是可以得到一个有序的in序列的,从小到大排序的一般是

4.键值最大的bst节点没有右儿子,键值最小的节点没有左儿子

上面就是bst的几个小性质,主要还是练手,其中练手题基本以bst的建立和遍历有关,说实话我见到的bst的题没怎么有删除的,当然poj的2418还没做,这个就不予评价了

pta:

https://pintia.cn/problem-sets/994805342720868352/problems/994805440976633856

https://pintia.cn/problem-sets/994805342720868352/problems/994805407749357568

https://pintia.cn/problem-sets/994805342720868352/problems/994805367987355648

hdu:

http://acm.hdu.edu.cn/showproblem.php?pid=3999

http://acm.hdu.edu.cn/showproblem.php?pid=3791

p:

http://poj.org/problem?id=2418(还没做不知道啥情况)

按顺序讲:

pta1043:

题目大意:

给定一个bst的序列,要求判断这个序列是否是bst的先序序列或者是镜像先序序列,所谓镜像就是交换左右子树,

如果是先序序列就输出YES并且输出后序序列

如果是镜像先序序列就输出YES同样输出镜像后序序列

两者都非是No;

问?怎么设计?

答:用vector会方便很多,这样就不用for循环判断了,其余的就是bst算法,用给定的序列建树,并且进行先序遍历和镜像先序遍历,并根据给的条件进行输出

参考code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 5 int n;
 6 vector<int>a;
 7 vector<int>pre;
 8 vector<int>post;
 9 vector<int>preM;
10 vector<int>postM;
11 struct node {
12     int data;
13     node *l;
14     node *r;
15     node(int data=0,node *l=NULL,node *r=NULL):data(data),l(l),r(r) {}
16 };
17 void insert(node *&root,int x) {
18     if(root==NULL) {
19         root=new node;
20         root->data=x;
21         root->l=root->r=NULL;
22         return ;
23     }  else if(root->data>x) {
24         insert(root->l,x);
25     } else {
26         insert(root->r,x);
27     }
28 }
29 
30 void preorder(node *&root) {
31     if(root!=NULL) {
32         pre.push_back(root->data);
33         preorder(root->l);
34         preorder(root->r);
35     }
36 }
37 void postorder(node *&root) {
38     if(root!=NULL) {
39         postorder(root->l);
40         postorder(root->r);
41         post.push_back(root->data);
42     }
43 }
44 void preorderM(node *&root) {
45     if(root!=NULL) {
46         preM.push_back(root->data);
47         preorderM(root->r);
48         preorderM(root->l);
49     }
50 }
51 void postorderM(node *&root) {
52     if(root!=NULL) {
53         postorderM(root->r);
54         postorderM(root->l);
55         postM.push_back(root->data);
56     }
57 }
58 node *buildtree(node *&root)
59 {
60     cin>>n;
61     for(int i=0; i<n; i++) {
62         int d;
63         cin>>d;
64         a.push_back(d);
65         insert(root,d);
66     }
67     return root;
68 }
69 signed main() {
70     IOS;
71     node *root=NULL;
72     root=buildtree(root);
73     preorder(root);
74     preorderM(root);
75     postorder(root);
76     postorderM(root);
77     if(pre==a) {
78         cout<<"YES"<<endl;
79         for(int i=0; i<post.size(); i++) {
80             cout<<post[i];
81             if(i<post.size()-1)
82                 cout<<" ";
83         }
84     } else if(preM==a) {
85         cout<<"YES"<<endl;
86         for(int i=0; i<postM.size(); i++) {
87             cout<<postM[i];
88             if(i<postM.size()-1)
89                 cout<<" ";
90         }
91     } else {
92         cout<<"NO";
93     }
94     return 0;
95 }

pta1064:

题目大意:给定一个序列,要求输出完全bst的层序遍历序列

完全bst是完全二叉树+bst

问?怎么做?

答:这个题就比较有意思了,因为你要是按照常规建树bfs,会发现不行。

其实我们可以设一个数组来表示经过bfs后的完全bst的序列,只不过还没有赋值

并且,对于一颗完全二叉树来讲,2*index是他的左孩子,2*index+1是右孩子,所以说我们在建树和遍历的过程中就可以充分利用这条性质

前面说到,bst的inorder得到的是一个有序的序列,我们就可以将题目给我们的序列进行一个排序,这样得到的就是一个中序bst序列,在将这个中序bst序列在中序遍历中挨个赋值给我们设计的bfs后的bst序列,最后输出就可以了

AC正确参考代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 5 const int N=1e3+10;
 6 struct node
 7 {
 8     int data;
 9     node *l;
10     node *r;
11     node(int data=0,node *l=NULL,node *r=NULL):data(data),l(l),r(r){}
12 };//其实这个结构体定不定义都无所谓了
13 int a[N];
14 int n;
15 int cbt[N];//经过bfs后的complete bst
16 int cnt=1;
17 void inorder(int root)
18 {
19     if(root>n)
20     return ;
21     inorder(root*2);//完全二叉树的性质左孩子
22     cbt[root]=a[cnt++];//将中序的序列挨个赋值
23     inorder(root*2+1);//右孩子
24 }
25 signed main()
26 {
27     IOS;
28     cin>>n;
29     for(int i=1;i<=n;i++)
30     cin>>a[i];
31     sort(a+1,a+1+n);//得到一个中序序列
32     inorder(1);//根节点从第一层开始
33     for(int i=1;i<=n;i++)
34     {
35         cout<<cbt[i];
36         if(i<n)
37         cout<<" ";
38     }
39     return 0;
40 }

再给一个错误代码以供鞭打:

wrong answer:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 5 const int N=1e3+10;
 6 int n;
 7 int a[N];
 8 int level[N];
 9 int cnt;
10 struct node
11 {
12     int data;
13     node *l;
14     node *r;
15     node(int data=0,node *l=NULL,node *r=NULL):data(data),l(l),r(r){}
16 };
17 void bfs(node *&root)
18 {
19     queue<node *>q;
20     q.push(root);
21     while(!q.empty())
22     {
23         node *now=q.front();
24         q.pop();
25         cout<<now->data;
26         cnt++;
27         if(cnt<n)
28         cout<<" ";
29         if(now->l!=NULL)
30         q.push(now->l);
31         if(now->r!=NULL)
32         q.push(now->r);
33     }
34 }
35 void insert(node *&root,int x)
36 {
37     if(root==NULL)
38     {
39         root=new node;
40         root->data=x;
41         root->l=root->r=NULL;
42         return ;
43     }
44     else if(root->data==x)
45     return ;
46     else if(root->data>x)
47     {
48         insert(root->l,x);
49     }
50     else
51     {
52         insert(root->r,x);
53     }
54 }
55 node *buildtree(node *&root)
56 {
57     for(int i=1;i<=n;i++)
58     {
59         insert(root,a[i]);
60     }
61     return root;
62 }
63 signed main()
64 {
65     IOS;
66     cin>>n;
67     for(int i=1;i<=n;i++)
68     cin>>a[i];
69     node *root=buildtree(root);
70     bfs(root);
71     //for(int i=1;i<=n;i++)
72     //{
73         //cout<<level[i];
74         //if(i<n)
75         //cout<<" "
76         //
77    // return 0;
78 }

 

pta1099

题目大意:给定一组不同数字的数组,并且有唯一的方式来填满这颗树

给定的输入是酱紫的:

9//总结点
1 6//左孩子,右孩子的下标,如果是-1就证明该位置没有孩子
2 3
-1 -1
-1 4
5 -1
-1 -1
7 -1
-1 8
-1 -1
73 45 11 58 82 25 67 38 42//给定的序列

题目要求输出这个bst的层序遍历序列

 

 问?咋弄?

答:用静态二叉树写法就可以啦,因为出现-1了,直接用静态二叉树来表示,如果节点是-1就相当于该位置NULL,如果你不嫌麻烦用二叉树写法也可以,判断该位置后赋一个NULL也行

其余的就是正常建树插入bfs了

参考code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 5 const int N=1e2+10;
 6 int a[N];
 7 int n;
 8 struct node
 9 {
10     int data;
11     int l;
12     int r;
13 }bst[N];
14 int cnt1;
15 int cnt2;
16  void bfs(int root)
17 {
18     queue<int>q;
19     q.push(root);
20     while(!q.empty())
21     {
22         int now=q.front();
23         q.pop();
24         cout<<bst[now].data;
25         cnt1++;
26         if(cnt1<n)
27         cout<<" ";
28         if(bst[now].l!=-1)
29         q.push(bst[now].l);
30          if(bst[now].r!=-1)
31         q.push(bst[now].r);
32     }
33 }
34 void inorder(int root)
35 {
36     if(root!=-1){
37         inorder(bst[root].l);
38         bst[root].data=a[cnt2++];
39         inorder(bst[root].r);
40     }
41 }
42 signed main()
43 {
44     IOS;
45     cin>>n;
46     for(int i=0;i<n;i++)
47     {
48         int lc,rc;
49         cin>>lc>>rc;
50         bst[i].l=lc;
51         bst[i].r=rc;
52     }
53     for(int i=0;i<n;i++)
54     cin>>a[i];
55     sort(a,a+n);
56     inorder(0);
57     bfs(0);
58     /*for(int i=1;i<=n;i++)
59     {
60         cout<<bst[i].data;
61         if(i<n)
62         cout<<" ";*/    
63     return 0;
64 }

hduoj 3999:

题目大意:

给定一组bst序列,要求和这颗树同构的字典序最小的序列

问?how deal with it?

答:一个先序遍历就够了?为甚么是先序遍历呢?先序遍历得到的是字典序最小码?

是的,因为先序序列是左-根-右的遍历形式

而bst的性质是根大于左而小于右,所以说一个先序遍历就可以求出字典序最小的同构序列了

参考代码:

  1  Problem: The order of  a Tree
  2 // Contest: HDOJ
  3 // URL: http://acm.hdu.edu.cn/showproblem.php?pid=3999
  4 // Memory Limit: 32 MB
  5 // Time Limit: 2000 ms
  6 // 
  7 // Powered by CP Editor
  8 #include<bits/stdc++.h>//hduoj 3999
  9 using namespace std;
 10 #define int long long
 11 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 12 const int N=1e5+10;
 13 int n;
 14 int a[N];
 15 int cnt1;
 16 int cnt2;
 17 int cnt3;
 18 int cnt4;
 19 int pre[N];
 20 int in[N];
 21 int post[N];
 22 int level[N];
 23 struct node {
 24     int data;
 25     node *l;
 26     node *r;
 27     node(int data=0,node *l=NULL,node *r=NULL):data(data),l(l),r(r) {}
 28 };
 29 void insert(node *&root,int x) {
 30     if(root==NULL) {
 31         root=new node;
 32         root->data=x;
 33         root->l=root->r=NULL;
 34         return ;
 35     }  else if(root->data>x) {
 36         insert(root->l,x);
 37     } else {
 38         insert(root->r,x);
 39     }
 40 }
 41 node *buildtree(node *&root)
 42 {
 43     for(int i=0; i<n; i++) {
 44         insert(root,a[i]);
 45     }
 46     return root;
 47 }
 48 void preorder(node *&root)
 49 {
 50     if(root!=NULL)
 51     {
 52         pre[cnt1++]=root->data;
 53         preorder(root->l);
 54         preorder(root->r);
 55     }
 56 }
 57 void inorder(node *&root)
 58 {
 59     if(root!=NULL)
 60     {
 61         inorder(root->l);
 62         in[cnt2++]=root->data;
 63         inorder(root->r);
 64     }
 65 }
 66 void postorder(node *&root)
 67 {
 68     if(root!=NULL)
 69     {
 70         postorder(root->l);
 71         postorder(root->r);
 72         post[cnt3++]=root->data;
 73     }
 74 }
 75 void bfs(node *&root)
 76 {
 77     queue<node *>q;
 78     q.push(root);
 79     while(!q.empty())
 80     {
 81         node *now=q.front();
 82         q.pop();
 83         cout<<now->data;
 84         cnt4++;
 85         if(cnt4<n)
 86         cout<<" ";
 87         if(now->l!=NULL)
 88         q.push(now->l);
 89         if(now->r!=NULL)
 90         q.push(root->r);
 91     }
 92 }
 93 signed main() {
 94     IOS;
 95     node *root=NULL;
 96     cin>>n;
 97     for(int i=0;i<n;i++)
 98     cin>>a[i];
 99     root=buildtree(root);
100     preorder(root);
101     for(int i=0;i<n;i++)
102     {
103         cout<<pre[i];
104         if(i<n-1)
105         cout<<" ";
106     }
107     cout<<endl;
108     return 0;
109 
110 }

hduoj 3791

题目大意:呸,中文题翻个pi

这道题是zju的研究生复试上机题,兄弟们给我冲

参考代码:

 1 // Problem: 二叉搜索树
 2 // Contest: HDOJ
 3 // URL: http://acm.hdu.edu.cn/showproblem.php?pid=3791
 4 // Memory Limit: 32 MB
 5 // Time Limit: 2000 ms
 6 //
 7 // Powered by CP Editor
 8 #include<bits/stdc++.h>//hduoj 3791
 9 using namespace std;
10 #define int long long
11 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
12 const int N=1e5+10;
13 int n;
14 using namespace std;
15 struct node{
16     node *l,*r;
17     char v;
18 };
19 void build(node *&a,char c)
20 {
21     if(a==NULL)
22     {
23         a=new node;
24         a->l=a->r=NULL;
25         a->v=c;
26         return;
27     }
28     if(c < a->v)
29         build(a->l,c);
30     else
31         build(a->r,c);
32 }
33 
34 bool cmp(node *a,node *b)
35 {
36     if(a==NULL&&b==NULL)
37         return true;
38     if((a==NULL&&b!=NULL)||(a!=NULL&&b==NULL))
39         return false;
40     if(a->v!=b->v)
41         return false;
42     return cmp(a->l,b->l)&&cmp(a->r,b->r);
43 }
44 
45 signed main()
46 {
47     IOS;
48     while(cin>>n&&n)
49     {
50         node *root=NULL,*tree=NULL;
51         string str1,str2;
52         cin>>str1;
53         for(int i=0;i<str1.size();i++)
54         {
55             build(root,str1[i]);
56         }
57         for(int i=0;i<n;i++)
58         {
59             cin>>str2;
60             if(str1.size()!=str2.size())
61                 printf("NO\n");
62             else
63             {
64                 tree=NULL;
65                 for(int j=0;j<str2.size();j++)
66                 {
67                     build(tree,str2[j]);
68                 }
69                 if(cmp(root,tree))
70                     printf("YES\n");
71                 else
72                     printf("NO\n");
73             }
74         }
75     }
76     return 0;
77 }

poj 2418没做不知道难度,不过肯定也不好做

posted @ 2022-08-16 21:39  江上舟摇  阅读(60)  评论(0编辑  收藏  举报