顺序结构实现树,二叉树的重建
二叉树的链式存储结构
struct Node
{
bool have_value;
int v;
Node *left, *right;
Node():have_value(false), left(NULL), right(NULL){}
};
二叉树的顺序存储结构
const int n = 10;
char data[n];
char lchild[n];
char rchild[n];
int bt;
表达式
(
a
+
b
∗
(
c
−
d
)
−
e
/
f
)
(a+b*(c-d)-e/f)
(a+b∗(c−d)−e/f)
的二叉树,用顺序存储结构实现
#include <bits/stdc++.h>
using namespace std;
const int n = 11;
char data[n]= {'-','+','/','a','*','e','f','b','-', 'c', 'd'};
int lch[n]={ 1, 3, 5, 0, 7, 0, 0, 0, 9, 0, 0};
int rch[n]={ 2, 4, 6, 0, 8, 0, 0, 0, 10, 0, 0};
int bt=0;
void perorder(int u)
{
printf("%c ",data[u]);
if(lch[u] == 0 && rch[u] == 0)
return;
if(lch[u])perorder(lch[u]);
if(rch[u])perorder(rch[u]);
}
void inorder(int u)
{
if(lch[u])inorder(lch[u]);
printf("%c ",data[u]);
if(rch[u])inorder(rch[u]);
if(lch[u] == 0 && rch[u] == 0)
return;
}
void postorder(int u)
{
if(lch[u])postorder(lch[u]);
if(rch[u])postorder(rch[u]);
printf("%c ",data[u]);
if(lch[u] == 0 && rch[u] == 0)
return;
}
int main()
{
printf("层序(不是真正的)遍历的结果是:\n");
for(int i = 0; i < n; i++)
printf("%c ", data[i]);
printf("\n");
printf("前序遍历的结果是:\n");
perorder(bt);
printf("\n");
printf("中序遍历的结果是:\n");
inorder(bt);
printf("\n");
printf("后序遍历的结果是:\n");
postorder(bt);
return 0;
}
层序(不是真正的)遍历的结果是:
- + / a * e f b - c d
前序遍历的结果是:(前缀表示、波兰式)
- + a * b - c d / e f
中序遍历的结果是:(中缀表示)
a + b * c - d - e / f
后序遍历的结果是:(后缀表示,逆波兰式)
a b c d - * + e f / -
二叉树的重建:中序+后序->前序
由中序和后序重建树,之后输出前序的结果,同时用dfs找到一个叶子使得它到根的路径上的权值和最小,这种重建树的方法,由于权重各不相同,所以以权值作为索引
#include <bits/stdc++.h>
using namespace std;
const int maxv = 10000 + 10;
int inorder[maxv];
int postorder[maxv];
int n;
int lch[maxv];
int rch[maxv];
bool read_list(int* a)
{
string line;
if(!getline(cin, line))return false;
stringstream ss(line);
n = 0;
int x;
while(ss >> x)a[n++] = x;
return n>0;
}
int build(int L1, int R1, int L2, int R2)
{
if(L1 > R1)return 0;
int root = postorder[R2];
//printf("root is %d\n",root);
int p = L1;
while(inorder[p] != root)p++;
int cnt = p-L1;
lch[root] = build(L1, p-1, L2, L2+cnt-1);
rch[root] = build(p+1,R1, L2+cnt, R2-1);
return root;
}
int best, best_sum=1000000000;
void dfs(int u, int sum)
{
sum += u;
if(lch[u] == 0 && rch[u] == 0)
{
if(sum < best_sum || (sum == best_sum && u < best))
{
best = u;
best_sum = sum;
printf("best is %d, best_sum is %d\n", best, best_sum);
}
}
if(lch[u])dfs(lch[u], sum);
if(rch[u])dfs(rch[u], sum);
}
void perorder(int u)
{
printf("%d ",u);
if(lch[u] == 0 && rch[u] == 0)
return;
if(lch[u])perorder(lch[u]);
if(rch[u])perorder(rch[u]);
}
int main()
{
// for(int i = 0; i < n; i++)
// {
// cout << inorder[i] << " " << postorder[i] << endl;
// }
while(read_list(inorder))
{
read_list(postorder);
// for(int i = 0; i < n; i++)
// {
// cout << inorder[i] << " " << postorder[i] << endl;
// }
build(0, n-1, 0, n-1);
for(int i = 0; i < 8; i++)
printf("%d ", i);printf("\n");
printf("lch is:\n");
for(int i = 0; i < 8; i++)
printf("%d ", lch[i]);printf("\n");
printf("rch is :\n");
for(int i = 0; i < 8; i++)
printf("%d ", rch[i]);printf("\n");
printf("perorder is :\n");
perorder(postorder[n-1]);
printf("\n");
printf("Minimum leaf :\n");
dfs(postorder[n-1], 0);
printf("best is %d\n", best);
}
return 0;
}
//输入
3 2 1 4 5 7 6
3 1 2 5 6 7 4
//输出
0 1 2 3 4 5 6 7
lch is:
0 0 3 0 2 0 0 5
rch is :
0 0 1 0 7 0 0 6
perorder is :
4 2 3 1 7 5 6
Minimum leaf :
best is 3, best_sum is 9
best is 1, best_sum is 7
best is 1
直接由前序+中序->后序
这里直接输出,没有重建树
其中特别需要注意的是,calc递归传进去的值,一定要考虑清楚,借用左子树的节点数这个变量,博主一开始就是有些小地方没注意到,错了,所以结果不对
#include <bits/stdc++.h>
using namespace std;
string s1, s2;
void calc(int l1, int r1, int l2, int r2)
{
int m = s2.find(s1[l1]);
//左子树的节点数
int num = m-l2;
//printf("%d\n", m);
if(m > l2)calc(l1+1, l1+1+num-1, l2, m-1);
if(m < r2)calc(l1+1+num-1+1, r1, m+1, r2);
cout << s1[l1];
}
int main()
{
cin >> s1 >> s2;
//cout << s1 << " " << s2;
calc(0, s1.length()-1, 0, s2.length()-1);
return 0;
}
//输入
abdec
dbeac
//输出
debca
//输入
adbgcefh
dgbaechf
//输出
gbdehfca
//输入
ABDHIEJCFKG
HDIBEJAFKCG
//输出
HIDJEBKFGCA
直接由后序+中序->前序
由上边的例子修改的
#include <bits/stdc++.h>
using namespace std;
string s1, s2;
void calc(int l1, int r1, int l2, int r2)
{
int m = s2.find(s1[r1]);
//左子树的节点数
int num = m-l2;
cout << s1[r1];
if(m > l2)calc(l1, l1+num-1, l2, m-1);
if(m < r2)calc(l1+num, r1-1, m+1, r2);
}
int main()
{
cin >> s1 >> s2;
//cout << s1 << " " << s2;
calc(0, s1.length()-1, 0, s2.length()-1);
return 0;
}
//输入
debca
dbeac
//输出
abdec
//输入
HIDJEBKFGCA
HDIBEJAFKCG
//输出
ABDHIEJCFKG
//输入
gbdehfca
dgbaechf
//输出
adbgcefh
前序+后序->中序
有多组解,此处不研究