A1020 Tree Traversals
/*
题意:由二叉树的后序遍历和中序遍历求得二叉树的层序遍历
题解:
·定义结点结构体
·由后序和中序遍历序列构造树
·对树进行层序遍历BFS
*/
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 50;
//定义结点结构体
struct node {
int data;
node* lchild;
node* rchild;
};
int pre[maxn],in[maxn],post[maxn]; //先序、中序及后序
int n; //结点个数
//当前二叉树的后序序列区间为[postL,postR],中序序列区间为[inL,inR]
//create函数返回构建出的二叉树的根结点地址
node* create(int postL,int postR,int inL,int inR){
if(postL > postR){
return NULL; //若后序序列长度小于等于0,则直接返回
}
node* root = new node; //新建一个新的结点,用来存放当前二叉树的根结点
root->data = post[postR]; //新结点的数据域为根结点的值
int k;
for(k = inL; k <= inR; k++){
if(in[k] == post[postR]){ //在中序序列中找到in[k] == pre[L]的结点
break;
}
}
int numLeft = k - inL;// 左子树的结点个数
//返回左子树的根结点地址,赋值给root的左指针
root->lchild = create(postL,postL+numLeft-1,inL, k-1);
//返回右子树的根结点地址,赋值给root的右指针
root->rchild = create(postL+numLeft, postR-1,k+1,inR);
return root; //返回根结点地址
}
int num = 0; //已输出的结点个数
void BFS(node* root){
queue<node*> q; //注意队列里是存地址
q.push(root); //根结点地址入队
while(!q.empty()){
node* now = q.front(); //取出队首元素
q.pop();
printf("%d",now->data); //访问队首元素
num++;
if(num < n) printf(" ");
if(now->lchild != NULL) q.push(now->lchild); //左子树非空
if(now->rchild != NULL) q.push(now->rchild);//右子树非空
}
}
int main(){
scanf("%d",&n);
for(int i = 0; i < n; i++){
scanf("%d",&post[i]);
}
for(int i = 0; i < n; i++){
scanf("%d",&in[i]);
}
node* root = create(0,n-1,0,n-1); //建树
BFS(root); //层序遍历
return 0;
}
/*
·题意:由先序和中序序列得出后序序列
·题解:注意从输入中得出先序和中序序列。push为先序,pop为后序。
*/
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 50;
struct node{
int data;
node* lchild;
node* rchild;
};
int pre[maxn],in[maxn];
int n;
node* create(int preL,int preR,int inL,int inR){
if(inL > inR){
return NULL;
}
node* root = new node;
root->data = pre[preL];
int k;
for(k = 0; k < inR; k++){
if(pre[preL] == in[k]) break;
}
int numLeft = k - inL;
root->lchild = create(preL+1,preL+numLeft,inL,k-1);
root->rchild = create(preL+numLeft+1,preR,k+1,inR);
return root;
}
int num = 0;
void postorder(node* root){
if(root == NULL){
return ;
}
postorder(root->lchild);
postorder(root->rchild);
printf("%d",root->data);
num++;
if(num < n) printf(" ");
}
int main(){
scanf("%d",&n);
char str[5];
stack<int> st;
int x,preIndex=0,inIndex = 0;
for(int i = 0; i < n*2; i++){
scanf("%s",str);
if(strcmp(str,"Push") == 0){
scanf("%d",&x);
pre[preIndex++] = x;
st.push(x);
} else{
in[inIndex++] = st.top();
st.pop();
}
}
node* root = create(0,n-1,0,n-1);
postorder(root);
return 0;
}
A1102 Invert a Binary Tree
题意:反转二叉树然后输出层序遍历序列和中序遍历序列。
题解:反转二叉树的操作只需要进行后序遍历,在后序遍历访问根结点时交换lchild和rchild即可。
这道题刚开始输出格式我没看懂。。。
Then N lines follow, each corresponds to a node from 0 to N−1, and gives the indices of the left and right children of the node.
意思:每行对应结点0-n-1,第n行的内容是结点n-1的左右孩子结点。 类似于数组,有两个元素,下标和下标所对应的值。
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 110;
//二叉树的静态写法
struct node{
int lchild,rchild;
}Node[maxn];
bool notRoot[maxn] = {false}; //记录是否不是根结点,初始均是根结点
int n, num = 0; //n为结点个数,num为已经输出的结点个数
//print函数输出结点id的编号
void print(int id){
printf("%d",id); //输出id
num++; //已经输出的结点个数+1
if(num < n) printf(" ");
else printf("\n");
}
//中序遍历
void inOrder(int root){
if(root == -1) return ;
inOrder(Node[root].lchild);
print(root);
inOrder(Node[root].rchild);
}
//层序遍历
void BFS(int root){
queue<int> q; // 注意队列里存的是地址
q.push(root); // 根结点地址入队
while(!q.empty()){
int now = q.front(); //取出队首元素
q.pop();
print(now);
if(Node[now].lchild != -1) q.push(Node[now].lchild);
if(Node[now].rchild != -1) q.push(Node[now].rchild);
}
}
//后序遍历,反转二叉树
void postOrder(int root){
if(root == -1) return ;
postOrder(Node[root].lchild);
postOrder(Node[root].rchild);
swap(Node[root].lchild,Node[root].rchild); //交换左右孩子结点
}
//将输入的字符转换为-1或结点编号
int strToNum(char c){
if(c == '-') return -1; //'-'表示没有孩子结点,记为-1
else{
notRoot[c - '0'] = true; //标记c不是根结点
return c-'0'; //返回结点编号
}
}
//寻找根结点编号
int findRoot(){
for(int i = 0; i < n; i++){
if(notRoot[i] == false){
return i; //是根结点,返回i
}
}
}
int main(){
char lchild,rchild;
scanf("%d",&n); //结点个数
for(int i = 0; i < n; i++){
scanf("%*c%c %c",&lchild,&rchild); //左右孩子结点
Node[i].lchild = strToNum(lchild);
Node[i].rchild = strToNum(rchild);
}
int root = findRoot(); //获得根结点编号
postOrder(root); //后序遍历,反转二叉树
BFS(root); //输出层序遍历序列
num = 0;
inOrder(root); //输出中序遍历序列
return 0;
}