L2-011 玩转二叉树 (25 分)
给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N
(≤30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int z[maxn],qq[maxn],tree[maxn],ans[maxn];
queue<int> q;
void build(int n,int zl,int zr,int qql,int qqr)
{
if(zl>zr||qql>qqr) return ;
if(zl==zr){
tree[n]=z[zl];return ;
}
for(int i=zl;i<=zr;i++)
{
if(z[i]==qq[qql])
{
tree[n]=qq[qql];
build(2*n+2,i+1,zr,qql+i-zl+1,qqr);
build(2*n+1,zl,i-1,qql+1,qqr+i-zl);
break;
}
}
}
void bfs(int x)
{
q.push(x);
int l=0;
while(!q.empty())
{
int y=q.front();
q.pop();
if(tree[y]==0) continue;
ans[l++]=tree[y];
q.push(2*y+2);
q.push(2*y+1);
}
}
int main()
{
int n;
cin>>n;
memset(tree,0,sizeof(tree));
memset(ans,0,sizeof(ans));
for(int i=0;i<n;i++)
cin>>z[i];
for(int i=0;i<n;i++)
cin>>qq[i];
build(0,0,n-1,0,n-1);
bfs(0);
for(int i=0;i<n;i++){
if(i!=n-1) printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
return 0;
}
L2-004 这是二叉搜索树吗? (25 分)
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,
- 其左子树中所有结点的键值小于该结点的键值;
- 其右子树中所有结点的键值大于等于该结点的键值;
- 其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。
给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
输入格式:
输入的第一行给出正整数 N(≤1000)。随后一行给出 N 个整数键值,其间以空格分隔。
输出格式:
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出 YES
,然后在下一行输出该树后序遍历的结果。数字间有 1 个空格,一行的首尾不得有多余空格。若答案是否,则输出 NO
。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
int q[1005],n,mirror;
vector<int> h;
void get(int l,int r)
{
if(l>r) return ;
int i=l+1,j=r;
if(mirror==0){
while(i<=r&&q[i]<q[l]) i++;
while(j>=l+1&&q[j]>=q[l]) j--;
}
else{
while(i<=r&&q[i]>=q[l]) i++;
while(j>=l+1&&q[j]<q[l]) j--;
}
//printf("%d %d\n",i,j);
if(i!=j+1) return ;
get(l+1,j);
get(i,r);
h.push_back(q[l]);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++){
cin>>q[i];
}
mirror=0;
get(0,n-1);
if(h.size()<n){
mirror=1;
h.clear();
get(0,n-1);
}
if(h.size()==n){
cout<<"YES"<<endl;
for(int i=0;i<n;i++){
if(i!=n-1) cout<<h[i]<<" ";
else cout<<h[i]<<endl;
}
}
else{
cout<<"NO"<<endl;
}
return 0;
}
L2-006 树的遍历 (25 分)
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int z[maxn],h[maxn],tree[maxn],ans[maxn];
queue<int> q;
void build(int n,int zl,int zr,int hl,int hr)
{
if(zl>zr||hl>hr) return ;
if(zl==zr){
tree[n]=z[zl];return ;
}
for(int i=zl;i<=zr;i++)
{
if(z[i]==h[hr])
{
tree[n]=h[hr];
build(2*n+1,zl,i-1,hl,hl+i-1-zl);
build(2*n+2,i+1,zr,hl+i-zl,hr-1);
break;
}
}
}
void bfs(int x)
{
q.push(x);
int l=0;
while(!q.empty())
{
int y=q.front();
q.pop();
if(tree[y]==0) continue;
ans[l++]=tree[y];
q.push(2*y+1);
q.push(2*y+2);
}
}
int main()
{
int n;
cin>>n;
memset(tree,0,sizeof(tree));
memset(ans,0,sizeof(ans));
for(int i=0;i<n;i++)
cin>>h[i];
for(int i=0;i<n;i++)
cin>>z[i];
build(0,0,n-1,0,n-1);
bfs(0);
for(int i=0;i<n;i++){
if(i!=n-1) printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
return 0;
}
将一系列给定数字顺序插入一个初始为空的小顶堆H[]
。随后判断一系列相关命题是否为真。命题分下列几种:
x is the root
:x
是根结点;x and y are siblings
:x
和y
是兄弟结点;x is the parent of y
:x
是y
的父结点;x is a child of y
:x
是y
的一个子结点。
输入格式:
每组测试第1行包含2个正整数N
(≤ 1000)和M
(≤ 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[−10000,10000]内的N
个要被插入一个初始为空的小顶堆的整数。之后M
行,每行给出一个命题。题目保证命题中的结点键值都是存在的。
输出格式:
对输入的每个命题,如果其为真,则在一行中输出T
,否则输出F
。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,m,x,a[maxn],cnt,i;
map<int,int> mm;
void join(int x)
{
cnt++;
for(i=cnt;a[i/2]>x;i/=2){
if(i==1) break;
a[i]=a[i/2];
}
a[i]=x;
}
int main()
{
cnt=0;
cin>>n>>m;
memset(a,0,sizeof(a));
for(int i=0;i<n;i++){
cin>>x;
join(x);
}
for(int i=1;i<=n;i++){
mm[a[i]]=i;
}
string s,ss,sss,ssss;
int aa,bb;
for(int i=0;i<m;i++){
cin>>aa;
cin>>s;
if(s=="is"){
cin>>ss;
if(ss=="the"){
cin>>sss;
if(sss=="root"){
if(mm[aa]==1) cout<<"T"<<endl;
else cout<<"F"<<endl;
}
else{
cin>>ssss>>bb;
if(mm[aa]==mm[bb]/2) cout<<"T"<<endl;
else cout<<"F"<<endl;
}
}
else{
cin>>sss>>ssss>>bb;
if(mm[aa]/2==mm[bb]) cout<<"T"<<endl;
else cout<<"F"<<endl;
}
}
else{
cin>>bb>>sss>>ssss;
if(mm[aa]/2==mm[bb]/2) cout<<"T"<<endl;
else cout<<"F"<<endl;
}
}
return 0;
}
HDU3999
建立二叉搜索树 输出它的层序遍历
用结构体数组下标表示该节点的值,左右子树为它的左右值,用while(1)循环建立树,如果该节点不可以,转换到下一左或右节点。
用dfs输出时,如果没有值,跳过,有值,记录再遍历它的左右子树。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const double pi=acos(-1);
const int maxn=1e5+5;
int n,root,ans[maxn];
struct node
{
int l,r;
}tree[maxn];
void join(int x)
{
int y=root;
while(1){
if(x>y){
if(!tree[y].r){
tree[y].r=x;return ;
}
else y=tree[y].r;
}
else{
if(!tree[y].l){
tree[y].l=x;return ;
}
else y=tree[y].l;
}
}
}
int l=0;
void dfs(int y){
if(y==0) return ;
ans[l++]=y;
dfs(tree[y].l);
dfs(tree[y].r);
}
int main()
{
cin>>n;
int x;
memset(tree,0,sizeof(tree));
for(int i=0;i<n;i++){
cin>>x;
if(i==0) root=x;
else join(x);
}
dfs(root);
for(int i=0;i<n;i++){
if(i!=n-1) printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
return 0;
}