二叉树的遍历和创建

Posted by Chenyawei on 2019-12-06
Words 1.1k and Reading Time 6 Minutes
Viewed Times

1. 二叉树的遍历

先序遍历、中序遍历、后序遍历,无论这三种遍历的哪一种,左子树一定先与右子树遍历;所谓的“先中后”是指访问根结点顺序在遍历中的位置。例外还有层次遍历,即广度优先遍历

  • 先序:根结点->>左子树->>右子树

    1
    2
    3
    4
    5
    6
    7
    void preOrder(node* root){ //先序遍历
    if(root == NULL){
    return;
    }
    preOrder(root->lchild);
    preOrder(root->rchild);
    }
  • 中序:左子树->>根结点->>右子树

    1
    2
    3
    4
    5
    6
    7
    8
    void inOrder(node* root){ //中序遍历
    if(root == NULL){
    return;
    }
    inOrder(root->lchild);
    printf("%d",root->data);
    inOrder(root->rchild);
    }
  • 后序:左子树->>右子树->>根结点

    1
    2
    3
    4
    5
    6
    7
    8
    void postOrder(node* root){ //后序遍历
    if(root == NULL){
    return;
    }
    postOrder(root->lchild);
    postOrder(root->rchild);
    printf("%d",root->data);
    }
  • 层次遍历(BFS遍历)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void BFS(node* root){  //层次遍历
    queue<node*> q;
    q.push(root);
    while(!q.empty()){
    node* now = q.front();
    q.pop();
    printf("%d",now->data);
    if(now->lchild != NULL) q.push(now->lchild);
    if(now->rchild != NULL) q.push(now->rchild);
    }
    }

2. 创建二叉树

中序序列可以与先序序列、后序序列、层序序列中的任意一个来构建唯一的二叉树,而后三者两两搭配或是三个一起上都无法构建唯一的二叉树。原因是先序、后序、层序均是提供根结点,功能是相同的,都必须由中序序列来区分出左右子树。

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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;

struct node{
node* lchild;
node* rchild;
int data;
};

int n;
vector<int> pre;
vector<int> in;
vector<int> post;
vector<int> layer;

//根据中序和后序,创建二叉树
node* createByPostAndIn(int postL, int postR, int inL, int inR){
if(postL > postR) return NULL;
node* root = new node;
root->data = post[postR];
int k;
for(k = inL; k <= inR; k++){
if(in[k] == post[postR]){
break;
}
}
int numLeft = k - inL; //左子树的结点个数
root->lchild = createByPostAndIn(postL, postL + numLeft - 1, inL, k - 1);
root->rchild = createByPostAndIn(postL + numLeft, postR - 1, k + 1, inR);
return root;
}

//根据中序和前序,创建二叉树
node* createByPreAndIn(int preL, int preR, int inL, int inR){
if(preL > preR) return NULL;
node* root = new node;
root->data = pre[preL];
int k;
for(k = inL; k <= inR; k++){
if(in[k] == pre[preL]){
break;
}
}
int numLeft = k - inL; //左子树的结点个数
root->lchild = createByPreAndIn(preL + 1, preL + numLeft, inL, k - 1);
root->rchild = createByPreAndIn(preL + numLeft + 1, preR, k + 1, inR);
return root;
}

//根据中序和层序创建二叉树
node* createByLayerAndIn(vector<int> layer, vector<int> in, int inL, int inR){
if(inL > inR || layer.size() == 0) return NULL;
node* root = new node;
root->data = layer[0];
int pos;
for(pos = inL; pos <= inR; pos++){
if(in[pos] == layer[0]){
break;
}
}
vector<int> layerLeft, layerRight; //存放左、右子树的层序序列
for(int i = 1; i < layer.size(); i++){
int j;
for(j = inL; j < pos; j++){
if(in[j] == layer[i]){
layerLeft.push_back(layer[i]); //如果在pos前找到,插入左子树
break;
}
}
//超过pos,j==pos时即为在左子树中没有找到插入右子树(层序遍历保持左右子树层序遍历顺序的一致性)
if(j == pos) layerRight.push_back(layer[i]);
}
root->lchild = createByLayerAndIn(layerLeft, in, inL, pos - 1);
root->rchild = createByLayerAndIn(layerRight, in, pos + 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);
}
}

void preOrder(node* root){ //先序遍历
if(root == NULL){
return;
}
printf("%d",root->data);
num++;
if(num < n){
printf(" ");
}
preOrder(root->lchild);
preOrder(root->rchild);
}

void inOrder(node* root){ //中序遍历
if(root == NULL){
return;
}
inOrder(root->lchild);
printf("%d",root->data);
num++;
if(num < n){
printf(" ");
}
inOrder(root->rchild);
}

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);
int temp;
for(int i = 0; i < n; i++){
scanf("%d",&temp);
in.push_back(temp);
}

/*测试数据:中后
7
1 2 3 4 5 6 7
2 3 1 5 7 6 4
*/
for(int i = 0; i < n; i++){
scanf("%d",&temp);
post.push_back(temp);
}
node* root = createByPostAndIn(0, n -1, 0, n -1);
/*测试数据:中前
7
1 2 3 4 5 6 7
4 1 3 2 6 5 7
*/
// for(int i = 0; i < n; i++){
// scanf("%d",&temp);
// pre.push_back(temp);
// }
// node* root = createByPreAndIn(0, n -1, 0, n -1);
/*测试数据:中层
7
1 2 3 4 5 6 7
4 1 6 3 5 7 2
*/
// for(int i = 0; i < n; i++){
// scanf("%d",&temp);
// layer.push_back(temp);
// }
// node* root = createByLayerAndIn(layer, in, 0, n -1);
BFS(root);
return 0;
}

notice

欢迎访问 chenyawei 的博客, 若有问题或者有好的建议欢迎留言,笔者看到之后会及时回复。 评论点赞需要github账号登录,如果没有账号的话请点击 github 注册, 谢谢 !

If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !