满二叉树(Full Binary Tree) 和 完全二叉树(Complete Binary Tree) 是两个不同的概念
A
/ \
B C
/ \ / \
D E F G
A
/ \
B C
/ \ /
D E F
一共n
个节点
开一个数组int tree[n<<2]
4倍大小
node<<1
表示左子树
node<<1|1
表示右子树
tree[]
中存的就是层序序列
提供的遍历 | 是否能唯一建树? | 说明 |
---|---|---|
中序 + 前序 | ✅ 能 | 最常见、能唯一建树 |
中序 + 后序 | ✅ 能 | 也可以唯一建树 |
前序 + 后序 | ❌ 一般不行 | 除非是满二叉树才行 |
只有一种遍历 | ❌ 不能 | 信息不够,多种可能的树 |
必须有一个中序序列 才能唯一确定一颗二叉树
如果你明确知道这棵树是完全二叉树,那情况就不一样了:
完全二叉树的关键特点是:节点编号是固定的!
比如:
1 -> root
2 -> left of root
3 -> right of root
4 -> left of node 2
...
这就是你前面用 node<<1
、node<<1|1
的核心!
遍历方式 | 是否能唯一建树? |
---|---|
前序+中序 / 中序+后序 | ✅ |
层序 + 完全二叉树 | ✅ |
前序/后序 + 完全二叉树结构 | ✅ |
只有一种遍历 | ❌ |
前序+后序 | ❌(除非满二叉树) |
const int N = 10;
int in[N],post[N],tree[N<<2];
int n;
//inl表示当前子树在中序序列中的起点 postl 后序序列起点
//len表示当前子树长度 (节点个数)
//pos用来分配节点在tree数组中的下标(pos<<1 左子树,pos<<1|1 右子树)
void build(int inl,int postl,int len,int pos){
int root = post[postl+len-1];
tree[pos]=root;
if(len==1) return;
int i=0;
while(in[inl+i]!=root) i++;//在中序序列中找到根的下标
int l=i,r=len-i-1;//l,r为左右子树长度
//左右子树非空就递归建树
if(l) build(inl, postl,l,pos<<1);
if(r) build(inl+l+1,postl+l,r,pos<<1|1);
}
void preprint(int node){
if(node>n*4||tree[node]==0){
return;
}
cout<<(char)(tree[node]-1+'A');
preprint(node<<1);
preprint(node<<1|1);
}
void solve(){
string s;cin>>s;
for(int i=0;i<s.size();i++){
in[i]=s[i]-'A'+1;
}
cin>>s;
for(int i=0;i<s.size();i++){
post[i]=s[i]-'A'+1;
}
n=s.size();
build(0,0,n,1);
preprint(1);
}
const int N = 2010;
int tree[N<<2],pre[N],in[N];
int n;
void build(int inl,int prel,int len,int pos){
int root=pre[prel];
tree[pos]=root;
if(len==1) return;
int i=0;
while(in[inl+i]!=root) i++;
int l=i,r=len-i-1;
if(l) build(inl,prel+1,l,pos<<1);
if(r) build(inl+l+1,prel+l+1,r,pos<<1|1);
}
void postprint(int node){
if(tree[node]==-1){
return;
}
postprint(node<<1);
postprint(node<<1|1);
cout<<(char)(tree[node]-1+'A');
}
void solve(){
string s;
while(cin>>s){
n=s.size();
memset(tree,-1,sizeof tree);
memset(pre,0,sizeof pre);
memset(in,0,sizeof in);
for(int i=0;i<s.size();i++){
pre[i]=s[i]-'A'+1;
}
cin>>s;
for(int i=0;i<s.size();i++){
in[i]=s[i]-'A'+1;
}
build(0,0,n,1);
postprint(1);
cout<<endl;
}
}
#include
#include
#include
using namespace std;
const int MAXN = 2005;
char tree[MAXN]; // 用数组模拟树,编号从1开始
string s; // 前序输入的字符串(含#)
int pos; // 当前在字符串中处理到的位置
// 建树,参数是当前处理到的节点编号
void build(int node) {
if (pos >= s.size()) return;
if (s[pos] == '#') {
pos++; // 空节点,跳过
return;
}
tree[node] = s[pos++]; // 建立当前节点
build(node << 1); // 左儿子
build(node << 1 | 1); // 右儿子
}
// 中序遍历
void inOrder(int node) {
if (tree[node] == 0) return;
inOrder(node << 1);
cout << tree[node];
inOrder(node << 1 | 1);
}
// 后序遍历
void postOrder(int node) {
if (tree[node] == 0) return;
postOrder(node << 1);
postOrder(node << 1 | 1);
cout << tree[node];
}
// 层序遍历
void levelOrder(int root) {
queue<int> q;
if (tree[root]) q.push(root);
while (!q.empty()) {
int u = q.front(); q.pop();
cout << tree[u];
if (tree[u << 1]) q.push(u << 1);
if (tree[u << 1 | 1]) q.push(u << 1 | 1);
}
}
void levelOrder(){//这样也可以 因为tree中存的就是层序序列
int n=s.size();
for(int i=1;i<n*4;i++){
if(tree[i]) cout<<tree[i];
}
}
int main() {
while (cin >> s) {
memset(tree, 0, sizeof(tree));
pos = 0;
build(1); // 从1号节点开始建树
inOrder(1);
cout << " ";
postOrder(1);
cout << " ";
levelOrder(1);
cout << endl;
}
return 0;
}
void build(int node) {
if (pos >= s.size()) return;
if (s[pos] == '#') {
pos++; // 空节点,跳过
return;
}
tree[node] = s[pos++]; // 建立当前节点
build(node << 1); // 左儿子
build(node << 1 | 1); // 右儿子
}
gpt写的 不太懂
string in;
int tree[N<<2];
int build( int& index, int l, int r) {
if (l > r) return -1; // 递归出口
// 选择当前节点
int mid = (l + r) / 2;
if (in[mid] == '#') {
return -1; // 当前节点为空
}
// 生成当前节点,并填充到树中
int node = index++;
tree[node] = in[mid] - '0'; // 假设树节点的值为数字字符
// 递归构建左子树
int left = build(index, l, mid - 1);
// 递归构建右子树
int right = build(index, mid + 1, r);
return node;
}