已知中序和前序(或后序)遍历结果生成树


如题,已知中序和前序(或后序)遍历结果生成树,算法分为两部分,一部分为已知前序和中序,另一部分为已知后序和中序。

思路

已知前序和中序

  1. 定位树根,树根即当前前序的首节点。
  2. 定位树根位于中序的位置,该位置左边即左子树,右边即右子树。
  3. 递归左右子树。

已知后序和中序

同理

举例

已知

后序序列 LHDKEBFGCA 中序序列 HLDBEKAFCG

求解

  1. 由后序序列定位树根,树根为A
  2. 节点A的左子树的中序为HLDBEK,左子树的后序为LHDKEB,右子树的中序为FCG,右子树的后序为FGC
  3. 对于左子树,树根为B,继续第二步,对于右子树,树根为G,继续第二步。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//
// Created by Jumormt on 2018/3/17.
//
#include <iostream>
#include <cstring>

using namespace std;

struct Node{

Node(char v='0'):value(v), left(0), right(0){}
char value;
Node* left;
Node* right;
};

char pre[50] = "ABDHLEKCFG"; //前序序列
char mid[50] = "HLDBEKAFCG"; //中序序列
char post[50] = "LHDKEBFGCA"; //后序序列


class BiTree{

public:

BiTree(Node* n):root(n){}

// 定位c在中序遍历的位置
int Position(char c)
{
return strchr(mid,c)-mid;
}

// // 数组初始化树的方法
// // 注意要传入指针的引用,因为函数内试图改变指针的大小R=new Node;不加引用就是无效改变!!另外R->value = ch[i];是确实会改变传入指针所指对象的。
// void Create(Node *&R, int i)
// {
// if (ch[i]==0)
// R = NULL;
// else
// {
// R=new Node;
// R->value = ch[i];
// Create(R->left, 2*i);
// Create(R->right, 2*i+1);
// }
// }

// 已知前序和中序遍历整个树 注意传入新参为Node*& root,因为函数内试图改变指针的大小root=new Node;不加引用就是无效改变!!另外root->value = pre[i];是确实会改变传入指针所指对象的。
// root为当前遍历树的根节点,i为当前根节点在__前序__遍历pre的序号,j为在__中序__遍历中树序列mid始序号。
void PreMidCreate(Node*& root, int i, int j, int length){

if (length <= 0)
return;

root = new Node();

root->value = pre[i];

int pos = Position(pre[i]);

int lenL = pos - j;
int lenR = length - lenL - 1;

PreMidCreate(root->left, i+1, j, lenL);
PreMidCreate(root->right, i+1+lenL, pos+1, lenR);
}

// 已知后序和中序遍历整个树
// root为当前遍历树的根节点,i为当前根节点在__前序__遍历pre的序号,j为在__中序__遍历中树序列mid始序号。
void PostMidCreate(Node*& root, int i, int j, int length){

if (length <= 0)
return;

root = new Node();

root->value = post[i];

int pos = Position(post[i]);

int lenL = pos - j;
int lenR = length - lenL - 1;

PostMidCreate(root->left, i-1-lenR, j, lenL);
PostMidCreate(root->right, i-1, pos+1, lenR);
}

//前序遍历
void preOrder(Node* root){
if (root){
cout<<root->value<<" ";
preOrder(root->left);
preOrder(root->right);
}
}

// 中序遍历
void midOrder(Node* root){
if (root){
midOrder(root->left);
cout<<root->value<<" ";
midOrder(root->right);
}

}

// 后序遍历
void postOrder(Node* root){
if (root){
postOrder(root->left);
postOrder(root->right);
cout<<root->value<<" ";
}

}

void deleteTree(Node* node){
if (node){
deleteTree(node->left);
deleteTree(node->right);
delete node;
}
}

~BiTree(){
deleteTree(root);
}


Node* getRoot(){
return root;
}


private:

Node* root;
};


int main(){

Node* node = new Node();
BiTree tree(node);

tree.PreMidCreate(node, 0, 0, strlen(mid));

tree.preOrder(node);

}
-------------本文结束感谢您的阅读-------------

本文标题:已知中序和前序(或后序)遍历结果生成树

文章作者:ChengXiao

发布时间:2018年03月17日 - 19:03

最后更新:2018年03月17日 - 23:03

原始链接:http://chengxiao19961022.github.io/2018/03/17/已知中序和前序(或后序)遍历结果生成树/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

你的鼓励是我前进的动力~