基本性质:二叉树的每个结点最多有两个子结点,分别是左右结点,以它们为根的子树称为左子树、右子树。
二叉树主要包含两种树:每一层的结点数都是满的称为满二叉树,其第 i 层有个结点。
如果满二叉树只在最后一层有缺失,且缺失的编号都在最后,那么称为完全二叉树。
完全二叉树有如下几个性质:
1)i > 1 的结点,其父结点是 (int类型下)
2) 如果2 i > k,那么 i 没有孩子;如果2 i +1 > k,那么 i 没有右孩子
3)如果结点 i 没有孩子,那么它的左孩子是2 i ,右孩子是2 i + 1
二叉树基本定义类型:一般使用指针来实现
struct node{
int value; //结点的值
node * l, * r; //左、右结点
};
注意:新建一个node时,用new来动态申请内存,使用完毕应用delete释放内存,防止内存泄漏。
使用数组实现的二叉树会在后续补充。
二叉树的遍历方法:
1)宽度优先遍历:即一层一层的遍历二叉树自上而下,自左向右进行,因此使用队列实现搜索过程,即BFS。
2)深度优先遍历:主要包含三种遍历(DFS)
1.先序遍历:即按照父结点、左儿子、右儿子的顺序访问。
具体实现如下:
void preorder(node * root){
if (root != NULL){
post[k++] = root -> value; //输出
preorder(root -> l); //递归左子树
preorder(root -> r); //递归右子树
}
}
2.中序遍历:即按照左儿子、父结点、右儿子的顺序访问。
具体实现如下:
void inorder(node * root){
if (root != NULL){
inorder (root -> l); //递归左子树
post[k++] = root -> value; //输出值
inorder(root -> r); //递归右子树
}
}
3.后序遍历:即按照左儿子、右儿子、父结点的顺序访问。
具体实现如下:
void postorder(node * root){
if (root != NULL){
postorder(root -> l); //递归左子树
postorder(root -> r); //递归右子树
post[k++] = root -> value; //输出 父节点
}
}
注意:如果想要构建出这颗二叉树,必须要知道中序遍历,然后再加上先序或后序其中一个即可
下面给出一道二叉树的例题:hdu 1710 “Binary Tree Traversals”
输入二叉树的先序和中序遍历序列,求后序遍历。
输入样例:
先序:1 2 4 7 3 5 8 9 6
后序:4 7 2 1 8 5 9 3 6
输出样例:
后序:7 4 2 8 9 5 6 3 1
本题使用DFS实现,具体代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int pre[N], in[N], post[N];//先序后序中序
int k; //记录结点数
struct node{
int value;
node * l , * r;
node(int value = 0, node * l = NULL, node * r = NULL) : value(value),l(l), r(r) {} //使用初始化列表赋初值
};
void buildtree(int l, int r, int &t, node * &root){
int flag = - 1;
for (int i = l; i <= r; i++)
if (in[i] == pre[t]){ // 先序的第一个数是根结点,与对应的中序位置匹配
flag = i;
break; //找到了就跳出
}
if (flag == - 1) return; //没找到就return
root = new node(in[flag]); //新建结点
t++;
if (flag > l) buildtree(l, flag - 1, t, root -> l); //建立左子树
if (flag < r) buildtree(flag + 1, r, t, root -> r); //建立右子树
}
void preorder(node * root){ //先序遍历
if (root != NULL){
post[k++] = root -> value;
preorder(root -> l);
preorder(root -> r);
}
}
void inorder(node * root){ //中序遍历
if (root != NULL){
inorder (root -> l);
post[k++] = root -> value;
inorder(root -> r);
}
}
void postorder(node * root){ //后序遍历
if (root != NULL){
postorder(root -> l);
postorder(root -> r);
post[k++] = root -> value;
}
}
void remove_tree(node * root){ //释放空间,防止内存泄露
if (root == NULL) return;
remove_tree(root -> l);
remove_tree(root -> r);
delete root;
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> pre[i];
for (int i = 1; i <= n; i++) cin >> in[i];
node * root;
int t = 1;
buildtree(0, n, t, root);
k = 0;
preorder(root);//先序
inorder(root); //中序
postorder(root);//后序
for (int i = 0, cnt = 1; i < k; i++,cnt++) printf("%d%c",post[i], cnt == n ? cnt = 0,'\n': ' ');
remove_tree(root);
return 0;
}
运行样例得到的数据如下:
9
1 2 4 7 3 5 8 9 6
4 7 2 1 8 5 9 3 6
1 2 4 7 3 5 8 9 6 //先序遍历
4 7 2 1 8 5 9 3 6 //中序遍历
7 4 2 8 9 5 6 3 1 //后序遍历
总结:二叉树作为一种基础的数据结构,一般使用指针实现,其更多的用法希望能在以后的题目中应用到,我这里只是了解其初步用法,还仍需学习。