总结下面几道题:首先想好用什么数据类型去处理这些输入的数据,然后就是遍历过程的实现。要的不仅仅是数据结构的思想,还需要分析问题,解决问题的能力,还有就是代码语言工具的熟练度。
FBI树
题目链接
解题思路:
由题意可知,一开始输入的字符为根结点。然后一半一半分,左半部分为左子树,右半部分为右子树。然后再将左边的一半分,左边同样为此结点的左子树,右边为此结点的右子树。
不然看出,可以用递归的思想去实现此过程,而且这个过程很像二分查找。
题目要求输出这个二叉树的后序遍历。所以我们要输出左子树,右子树,根结点的顺序。
注意1处的位置,a,b对应的递归处,以及2处之间的逻辑关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include<iostream> using namespace std;
char s[1030];
void bianli(int low,int high){ if(low>high) return; int mid=(low+high)/2; if(low!=high){ bianli(low,mid); bianli(mid+1,high); }
int shua=0; for(int i=low;i<=high;i++){ if(s[i]=='1') shua++; } if(shua==high-low+1) cout<<"I"; else if(shua) cout<<"F"; else cout<<"B"; }
int main(){ int n; cin>>n; cin>>s+1; bianli(1,1<<n); return 0; }
|
求先序排列
题目链接
此题是一个典型的基础题。
用string类型的比较好操作,首先再后缀string中找到根结点,存在gen中,接着在中序遍历中找到根结点的位置(用find函数)。
然后进递归,substr(i,j)是输出i到j的字符,且不包含j字符。
递归部分的思想是:
比如有中序badc,后序bdca,那么,根结点是a。输出根结点a。
中序就变成b和dc两个子树,后序就变为b和dc两个子树。
那么问题就变成了1.求b中序遍历和b后序遍历的树,和2.中序遍历是dc和后序遍历是dc的树。
那么1.b就为根结点,输出。2.根结点是c,中序遍历分为左子树d,后序遍历变为左子树d。
那么输出根结点c,还有一个d,也成了根结点,输出。
总结:流程可以概括为,
step1:找到根并输出
step2:将中序,后序各分为左右两棵子树;
step3:递归,重复step1,2;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include<iostream> #include<string> using namespace std;
void hx(string xx,string zx){ if(xx.size()>0){ char gen=zx[zx.size()-1]; cout<<gen; int k=xx.find(gen); hx(xx.substr(0,k),zx.substr(0,k)); hx(xx.substr(k+1),zx.substr(k,xx.size()-k-1)); } }
int main(){ string xx,zx; cin>>xx>>zx; hx(xx,zx); return 0; }
|
新二叉树
题目链接
首先想好用什么数据类型存储数据,这里用结构体。其实本题的第一个输入的字母就是为根结点,是数据太水了,我们应该要按照一般的思想,先找到根结点是谁。
此题的思想是用每一个不同的数组下标分别指示一个字母,这样,就很方便的存储了输入的各个字母之间的树形结构的关系了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include<iostream> #include<string>
using namespace std;
struct node{ char l,r,farther; }tree[30];
void pre(char zf){ cout<<zf; if(tree[zf-97].l!='*') pre(tree[zf-97].l); if(tree[zf-97].r!='*') pre(tree[zf-97].r); } int main(){ int n; cin>>n; char root='*'; for(int i=0;i<26;i++) tree[i].farther='*'; for(int i=1;i<=n;i++){ char zf,zfl,zfr; cin>>zf>>zfl>>zfr; if(root=='*') root=zf; tree[zf-97].l=zfl; tree[zf-97].r=zfr; if(zfl!='*') tree[zfl-97].farther=zf; if(zfr!='*') tree[zfr-97].farther=zf; } while(tree[root-97].farther!='*') root=tree[root-97].farther; pre(root); cout<<endl; return 0; }
|
对称二叉树
题目链接
这一题中的子树概念是从一个结点(此时这个结点就是根结点)出发,要直到这个结点所在树的最底部,构成的树,才叫子树。
递归思想是:枚举根结点,判断其左右两个孩子节点是否存在以及是否相同,如果存在且点权相等,就递归左右两个孩子节点的左右两个孩子节点。
重复上述判断。
当上面的递归完成后,即判断好对称二叉树后,就可以计算以该节点为根结点的对称二叉子树的节点数量,然后以max函数取出最大的情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| #include<bits/stdc++.h> using namespace std; const int maxn=2000000; long long zhi[maxn]; long long leftt[maxn],rightt[maxn];
long long ans,n; bool flag;
long long zc(long long x) { long long sum = 0; if(leftt[x] != -1) sum += zc(leftt[x]); if(rightt[x] != -1) sum += zc(rightt[x]);
return sum + 1; }
void digui(long long a,long long b){ if(a==-1&&b==-1) return; if(a==-1||b==-1||zhi[a]!=zhi[b]){ flag=false; return; } digui(leftt[a],rightt[b]); digui(leftt[b],rightt[a]); }
int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>zhi[i]; } for(int i=1;i<=n;i++){ cin>>leftt[i]; cin>>rightt[i]; } ans=1; for(int i=1;i<=n;i++){ if(leftt[i]!=-1&&rightt[i]!=-1&&zhi[leftt[i]]==zhi[rightt[i]]){ flag=true; digui(leftt[i],rightt[i]); if(flag==true){ ans=max(ans,zc(i)); } } } cout<<ans; return 0; }
|