2022-07-15 12:23阅读: 37评论: 0推荐: 0

二叉树专题

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

Link

#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 中国大陆许可协议进行许可。

posted @   Ryomk  阅读(37)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.

作曲 : Reol

作词 : Reol

fade away...do over again...

fade away...do over again...

歌い始めの一文字目 いつも迷ってる

歌い始めの一文字目 いつも迷ってる

どうせとりとめのないことだけど

伝わらなきゃもっと意味がない

どうしたってこんなに複雑なのに

どうしたってこんなに複雑なのに

噛み砕いてやらなきゃ伝わらない

ほら結局歌詞なんかどうだっていい

僕の音楽なんかこの世になくたっていいんだよ

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.

目の前 広がる現実世界がまた歪んだ

目の前 広がる現実世界がまた歪んだ

何度リセットしても

僕は僕以外の誰かには生まれ変われない

「そんなの知ってるよ」

気になるあの子の噂話も

シニカル標的は次の速報

麻痺しちゃってるこっからエスケープ

麻痺しちゃってるこっからエスケープ

遠く遠くまで行けるよ

安定なんてない 不安定な世界

安定なんてない 不安定な世界

安定なんてない きっと明日には忘れるよ

fade away...do over again...

fade away...do over again...

そうだ世界はどこかがいつも嘘くさい

そうだ世界はどこかがいつも嘘くさい

綺麗事だけじゃ大事な人たちすら守れない

くだらない 僕らみんなどこか狂ってるみたい

本当のことなんか全部神様も知らない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.