二叉树专题
Complete Binary Search Tree (30)
Link
这道题相当于是已知完全二叉排序树的中序遍历,要输出其层序遍历。做法很巧妙,根本不用建树。
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <cmath> #include <unordered_set> using namespace std; int n,cur; int a[1010],b[1010]; void levelTraverse(int r){ if(r<=n){ levelTraverse(r<<1); b[r]=a[++cur]; levelTraverse((r<<1)+1); } } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); sort(a+1,a+1+n); levelTraverse(1); for(int i=1;i<n;++i) printf("%d ",b[i]); printf("%d\n",b[n]); return 0; }
我在官方OJ上做的时候, 想出了一种很巧妙的非递归解法:
Link
思路是: 假设完全二叉树从根节点开始层次遍历的所有节点依次编号为 1~n, 那么我先用栈存储下中序遍历这棵树的编号顺序, 也就是代码中 cnt 的遍历顺序. 由于中序遍历得到的一定是原数组 a 的增序排列, 因此将中序遍历的编号顺序与增序排列的值一次关联, 最后将编号顺序从小到大排序——也就得到了层次遍历的顺序. 一次输出与其关联的值即可.
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <stack> using namespace std; int n; int a[1010]; stack<int>st; struct node{ int index,val; bool operator<(node x)const{ return index<x.index; } }b[1010]; int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); sort(a+1,a+1+n); int cnt=1,num=1; st.push(cnt); while(!st.empty()){ cnt=st.top(); if((cnt<<1)<=n) st.push(cnt<<1); else{ st.pop(); b[num]={cnt,a[num]}; num++; while(!st.empty()){ cnt=st.top(); st.pop(); b[num]={cnt,a[num]}; num++; if((cnt<<1)+1<=n){ st.push((cnt<<1)+1); break; } } } } sort(b+1,b+1+n); for(int i=1;i<n;++i) printf("%d ",b[i].val); printf("%d\n",b[n].val); return 0; }
Root of AVL Tree (25)
Link
AVL模板题
借用网上的图在此解释一下4种旋转的情形:(左右图都是不平衡的AVL)
先左旋后右旋指的是先左旋左子树,后右旋根节点。实际上左子树是平衡的,但是左孩子(左子树的根节点)满足两边高度之差等于1,这就导致了根节点不平衡。如果左孩子的右子树高度比左子树高度大1,那么就要先左旋以左孩子为根节点的左子树(这就会让新的左孩子的左子树高度比右子树高度大1);如果左孩子的左子树高度比右子树高度大1,那么就不必进行任何操作。也就是说,这种情况下首先要让长度的不平衡集中到左孩子的左边,最后将根节点右旋即可。
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <cmath> using namespace std; struct node{ int val; struct node *left,*right; }; //return root //左旋的情况:根节点所在的树不平衡 node *rotateLeft(node *root){ node *t=root->right; root->right=t->left; t->left=root; return t; } node *rotateRight(node *root){ node *t=root->left; root->left=t->right; t->right=root; return t; } //先左旋后右旋的情况:先左旋左子树,后右旋根节点 //左子树平衡,但左子树的两边高度差是1,导致了根节点不平衡 node *rotateLeftRight(node *root){ //先在左子树上完成左旋 root->left=rotateLeft(root->left); //后右旋根节点 return rotateRight(root); } node *rotateRightLeft(node *root){ root->right=rotateRight(root->right); return rotateLeft(root); } int getHeight(node *root){ if(root==NULL) return 0; return max(getHeight(root->left),getHeight(root->right))+1; } node *insert(node *root,int val){ if(root==NULL){ root=new node(); root->val=val; root->left=root->right=NULL; }else if(val<root->val){ root->left=insert(root->left,val); if(getHeight(root->left)-getHeight(root->right)==2) root=val<root->left->val?rotateRight(root):rotateLeftRight(root); }else{ root->right=insert(root->right,val); if(getHeight(root->right)-getHeight(root->left)==2) root=val<root->right->val?rotateRightLeft(root):rotateLeft(root); } return root; } int main() { int n,val; scanf("%d",&n); node *root=NULL; for(int i=1;i<=n;++i){ scanf("%d",&val); root=insert(root,val); } printf("%d\n",root->val); return 0; }
Is It a Binary Search Tree (25)
Link
根据BST的前序遍历输出其后序遍历。不用建树。
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> using namespace std; int n; int a[1010]; bool isMirror=false; bool isBST=true; vector<int>ans; void build(int l,int r){ if(!isBST||l>r) return; int root=a[l]; if(isMirror){ int i=l+1; for(;i<=r;++i){ if(a[i]<a[l]) break; } for(int j=i;j<=r;++j){ if(a[j]>=a[l]){ isBST=false; break; } } build(l+1,i-1); build(i,r); }else{ int i=l+1; for(;i<=r;++i){ if(a[i]>=a[l]) break; } for(int j=i;j<=r;++j){ if(a[j]<a[l]){ isBST=false; break; } } build(l+1,i-1); build(i,r); } ans.push_back(root); } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); if(n==1){ printf("YES\n%d",a[0]); return 0; } if(n>1&&a[2]>=a[1]) isMirror=true; build(1,n); if(!isBST) printf("NO\n"); else{ printf("YES\n"); printf("%d",ans[0]); for(int i=1;i<ans.size();++i) printf(" %d",ans[i]); } return 0; }
第二次在官方OJ上做时提交的代码:
Link
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> using namespace std; int n; int a[1010]; bool flag=true; vector<int>ans; void Traverse(int l,int r){ if(l>r||r>n) return; int i=l+1; for(;i<=r;++i) if(a[i]>=a[l]) break; for(int j=i+1;j<=r;++j) if(a[j]<a[l]){ flag=false; break; } Traverse(l+1,i-1); Traverse(i,r); ans.push_back(a[l]); } void MirrorTraverse(int l,int r){ if(l>r||r>n) return; int i=l+1; for(;i<=r;++i) if(a[i]<a[l]) break; for(int j=i+1;j<=r;++j) if(a[j]>=a[l]){ flag=false; break; } MirrorTraverse(l+1,i-1); MirrorTraverse(i,r); ans.push_back(a[l]); } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); if(n==1){ printf("YES\n%d\n",a[1]); return 0; } if(a[2]<a[1]){ Traverse(1,n); }else{ MirrorTraverse(1,n); } if(!flag) printf("NO\n"); else{ printf("YES\n"); for(int i=0;i<n-1;++i) printf("%d ",ans[i]); printf("%d\n",ans[n-1]); } return 0; }
1086 Tree Traversals Again
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <stack> using namespace std; int n,num; char op[5]; vector<int>pre,in,post; stack<int>st; void Traverse(int l1,int r1,int l2,int r2){ if(l1>r1||l2>r2) return; int root=pre[l1],pos=0; for(int i=l2;i<=r2;++i) if(in[i]==root){ pos=i; break; } Traverse(l1+1,l1+pos-l2,l2,pos-1); Traverse(l1+pos-l2+1,r1,pos+1,r2); post.push_back(root); } int main() { scanf("%d",&n); for(int i=1;i<=(n<<1);++i){ scanf("%s",op); if(op[1]=='u'){ scanf("%d",&num); pre.push_back(num); st.push(num); }else{ in.push_back(st.top()); st.pop(); } } Traverse(0,n-1,0,n-1); for(int i=0;i<n-1;++i) printf("%d ",post[i]); printf("%d\n",post[n-1]); return 0; }
本文作者:Ryomk
本文链接:https://www.cnblogs.com/preccrep/p/16398174.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步