二叉树的遍历
二叉树的遍历方法有四种:先序遍历、中序遍历、后序遍历、层序遍历,其中前三种一般都使用深度优先搜索(DFS)实现,层序遍历一般使用广度优先搜索(BFS)实现。无论这三种中的哪一种,左子树一定优于右子树遍历。
先序遍历:根左右
中序遍历:左根右
后序遍历:左右根
先序遍历(根左右)
DFS代码~
void preorder(node* root){
if(root == NULL) return;
printf("%d\n",root->data);
preorder(root->lchild);
preorder(root->rchild);
}
中序遍历(左根右)
DFS代码~
void inorder(node* root){
if(root == NULL) return;
inorder(root->lchild);
printf("%d\n",root->data);
inorder(root->rchild);
}
后序遍历(左右根)
void postorder(node* root){
if(root == NULL) return ;
postorder(root->lchild);
postorder(root->rchild);
printf("%d\n",root->data);
}
层序遍历(BFS)
思路:
1、取出根结点root,加入队列q
2、取出队首结点,访问它
3、判断是否有左孩子,如果有,左孩子就入队
4、判断是否有右孩子,如果有,右孩子就入队
5、返回2、,直到队列为空
BFS代码~
void LayerOrder(node* root){
queue<node*> q; //注意这里的队列是存取地址
q.push(root);
while(!q.empty()){
node* now = q.front();
q.pop();
if(now->lchild != NULL) q.push(now->lchild);
if(now->rchild != NULL) q.push(now->rchild);
}
}
如果有些题目需要求出每个结点所处的层次:
修改结构:
struct node{
int data;
int layer;
node* lchild;
node* rchild;
};
修改算法:
void LayerOrder(node* root){
queue<node*> q;
root->layer = 1;
q.push(root);
while(!q.empty()){
node* now = q.front();
q.pop();
printf("%d\n",now->data);
if(now->lchild != NULL){
now->lchild->layer = now->layer + 1;
q.push(now->lchild);
}
if(now->rchild != NULL){
now->rchild->layer = now->layer + 1;
q.push(now->rchild);
}
}
}
如何根据一棵二叉树的先序和中序遍历序列重建这棵二叉树?
思路:假设k是中序序列的根结点在中序序列中的相对位置。事实上,如果递归过程中当前先序序列的区间是[preL,preR],中序序列的区间是[inL, inR], 那么左子树结点个数numLeft = k - inL。
这样子,左子树的先序序列区间就是[preL+1, preL+numLeft],左子树的中序序列区间就是[inL, k-1];
右子树的先序序列区间就是[preL+numLeft+1, preR],右子树的中序序列区间就是[k+1, inR]。
如果一直递归下去,只要先序序列的长度<=0,那么就停止。
代码如下~
node* create(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 = create(preL+1, preL+numLeft, inL, k-1);
root->rchild = create(preL+numLeft+1,preR, k+1, inR);
return root;
}
结论~
中序序列可以和先序序列、后序序列、层序序列中的一个组合来构建唯一的一棵二叉树;
后三者两两组合,或者三者组合都无法构成一棵二叉树,原因是后面三者都是提供二叉树,作用是相同的,必须有中序序列来区分出左子树和右子树~