二叉树(初步)

基本性质:二叉树的每个结点最多有两个子结点,分别是左右结点,以它们为根的子树称为左子树、右子树。

二叉树主要包含两种树:每一层的结点数都是满的称为满二叉树,其第 i 层有2^{i -1}个结点。

如果满二叉树只在最后一层有缺失,且缺失的编号都在最后,那么称为完全二叉树。

完全二叉树有如下几个性质:

1)i > 1 的结点,其父结点是 \frac{i}{2}(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    //后序遍历

总结:二叉树作为一种基础的数据结构,一般使用指针实现,其更多的用法希望能在以后的题目中应用到,我这里只是了解其初步用法,还仍需学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值