1.树的层号表示法
根据树的层号表示建树,打印树的后序遍历序列
样例输入:
5
(0,A) (1,B) (2,D) (2,E) (1,C)
样例输出:
DEBCA
#include <bits/stdc++.h>
#define maxn 30
#define INF 0x3f3f3f3f
using namespace std;
struct Dnode
{
char data;
int level;
};
struct Node
{
char data;
int level;
Node *child[maxn];
Node *parent;
Node(Dnode a)
{
data = a.data;
level = a.level;
for (int i=0; i<maxn; i++)
child[i] = NULL;
parent = NULL;
}
};
Dnode a[maxn];
Node* build_tree(Dnode *a, int n)
{
Node *root, *p, *q;
if (n < 1) return NULL;
root = new Node(a[0]);
p = root;
for (int i=1; i<n; i++)
{
q = new Node(a[i]);
while (p->level >= q->level)
p = p->parent;
q->parent = p;
int j = -1;
while (p->child[++j] != NULL);
p->child[j] = q;
p = q;
}
return root;
}
void postorder(Node *root)
{
if (root)
{
for (int i=0; i<maxn; i++)
{
if (root->child[i])
postorder(root->child[i]);
else break;
}
printf("%c", root->data);
}
}
int main()
{
int n;
scanf("%d", &n);
getchar();
for (int i=0; i<n; i++)
{
scanf("(%d,%c)", &a[i].level, &a[i].data);
getchar();
}
Node *root = build_tree(a, n);
postorder(root);
putchar('\n');
return 0;
}
2. 还原二叉树
给定一棵二叉树的先序遍历和中序遍历,要求计算出该二叉树的高度。
样例输入:
9
ABDFGHIEC
FDHGIBEAC
输出:
5
#include <bits/stdc++.h>
using namespace std;
string s1,s2;
typedef struct node{
char data;
struct node* lchild;
struct node* rchild;
}tree;
tree* creat()
{ tree*p=new tree;
p->lchild=p->rchild=NULL;
return p;
}
tree* recover(int x1,int x2,int y1,int y2){
tree*p=creat();
p->data=s1[x1];
for(int j=y1;j<=y2;j++){
if(s1[x1]==s2[j])
{ if(j!=y1)
p->lchild=recover(x1+1,x1+j-y1,y1,j-1);
if(j!=y2)
p->rchild=recover(x1+j-y1+1,x2,j+1,y2);
break;
}
}
return p;
}
int depth(tree *t)
{
if(t==NULL) return 0;
int m=depth(t->lchild);
int n=depth(t->rchild);
if(m>n)
return (m+1);
else
return (n+1);
}
int main()
{
int n;
cin>>n;
cin>>s1>>s2;
tree* p=recover(0,s1.size()-1,0,s2.size()-1);
cout<<depth(p)<<endl;
return 0;
}
3. 最小权值路径
已知一棵二叉树的中序遍历和后序遍历,从根结点到每个叶子结点存在一条路径,你需要找到其中权值最小的路径(路径的权值是在该路径上的所有结点的权值之和)并输出该叶子结点的权值(1≤结点数≤10000)
样例输入:
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
样例输出:
3
#include <bits/stdc++.h>
const int INF = 1000000;
struct node { // 二叉树结点
int data; // 数据域
node* left; // 左孩子
node* right; // 右孩子
};
node* build(int* in, int* post, int il, int ih, int pl, int ph) {
// 根据中序遍历in[il, ih]和后序遍历post[pl, ph]构造二叉树
if(il>ih) { // 空树
return NULL;
}
node* root = (node*)malloc(sizeof(node)); // 根节点
root->data = post[ph];
// 在中序遍历中寻找根节点,然后划分左右子树
int rootInd = il;
while(in[rootInd] != root->data) rootInd++;
int llen = rootInd - il; // 左子树的长度
int rlen = ih - rootInd;
root->left = build(in, post, il, il+llen-1, pl, pl+llen-1); // 递归构造左子树
root->right = build(in, post, rootInd+1, ih, pl+llen, ph-1); // 递归构造右子树
return root;
}
int getNum(char s[], int len, int a[]) {
// 将长度为len的字符串解析为整型数组,并返回长度
int num = 0; // 保存解析的数字
int ind = 0; // a的下标
for(int i=0; i<len; i++) {
if(s[i] == ' ') { // 空格为分割符,当前数字解析完成
a[ind++] = num;
num = 0; // 方便解析下一个数字
} else { // 数字
num = num * 10 + s[i] - '0';
}
}
a[ind++] = num; // 保存最后一个数字
return ind;
}
int minPath = INF;
int minnode;
void dfs(node* u, int sum) {
// 先序遍历二叉树,sum记录当前结点(不包含)到根节点的权值和
if(u!=NULL) { // 非空结点
if(u->right ==NULL && u->left ==NULL) { // 遍历到叶子结点
if(sum+u->data < minPath || (sum+u->data == minPath && u->data < minnode)) { // 找到更“优”叶子结点
minPath = sum+u->data;
minnode = u->data;
}
}
dfs(u->left, sum+u->data); // 递归遍历左子树
dfs(u->right, sum+u->data); // 递归遍历右子树
}
}
int main() {
char s1[4000], s2[4000];
int in[10000], post[10000]; // 中序和后序
int numcnt;
while(gets(s1) && gets(s2)) { // 接受两行字符串
getNum(s1, strlen(s1), in);
numcnt = getNum(s2, strlen(s2), post);
node* root = build(in, post, 0, numcnt-1, 0, numcnt-1); // 构造二叉树
minPath = INF; // 每次遍历都有初始化
minnode = root->data;
dfs(root, 0);
printf("%d\n", minnode);
}
return 0;
}