美文网首页
2. 二叉树 BinTree

2. 二叉树 BinTree

作者: 執著我們的執著 | 来源:发表于2018-06-08 00:25 被阅读0次

二叉树的实现

BinNode : 二叉树结点

BinNode

二叉树结点结构代码 :

#define BinNodePosi BinNode *

struct BinNode
{
    BinNodePosi parent, lchild, rchild;
    T Data;                                      //数据项,数据类型为T
    int height;                                  //该结点的高
    int size();                                  //子树的规模,包括该节点
    int color;                                  // 节点的颜色,RB-Tree使用
    BinNodePosi insertAsLC(T const &);           //作为左孩子插入新结点
    BinNodePosi insertAsRC(T const &);          //作为右孩子插入新结点
    BinNodePosi succ();                         //中序遍历下,当前结点的直接后继
    void travLevel();    //该结点(包括该结点)所在的子树层次遍历
    void travPre();      //该结点(包括该结点)所在的子树先序遍历
    void travIn();       //该结点(包括该结点)所在的子树中序遍历
    void travPost();     //该结点(包括该结点)所在的子树后续遍历
};


二叉树常用接口实现

  1. 将新结点作为左/右孩子插入
    • BinNodePosi insertAsLC(T const &); //作为左孩子插入新结点
    • BinNodePosi insertAsRC(T const &); //作为右孩子插入新结点
/* 创建一个新结点,该结点之后作为左孩子结点 */
BinNodePosi insertAsLC(T const &e)
{
    BinNodePosi lChild = new BinNode(e, this);  //this指针:父结点为当前结点;条件 : this.LC == NULL
    
    return lChild;
}

/* 创建一个新结点,该结点之后作为右孩子结点 */
BinNodePosi insertAsRC(T const &e)
{
    BinNodePosi rChild = new BinNode(e, this);  //this指针:父结点为当前结点;条件 : this.RC == NULL
    
    return rChild;
}
  1. 规模 size : 返回包括当前结点在内的所有后代的总数
int size()
{
    int s = 1;                               //计入自身
    if (lchild)
    {
        s + = lchild->size();               //递归计入左子树的规模
    }
    if (rchild)
    {
        s + = rchild->size();               //递归计入右子树的规模
    }

    return s;
}
  1. 高度更新
    某结点插入或删除后代结点,可能其高度以及其祖先结点的高度都会更新;(从插入或删除的结点的父结点[第一个高度可能更新的结点]开始更新)

[注] 结点高度 : 约定空(子)树高度为 0;单结点(子)树高度为 0

#define NodeHeight(p) ((p) ? p->height : 0)       //节点高度,约定空树的节点高度为 0

/* 更新当前结点 x 的高度 */
int updateHeight(BinNodePosi x)
{
    return x->height = 1 + max(NodeHeight(x->lchild), NodeHeight(x->rchild));
}

/* 更新 x 的高度及其历代祖先的高度 */
void updateHeightAbove(PinNodePosi x)
{
    while (x)
    {
        updateHeight(x);
        x = x->parent;
    }
    
    return;
}
  1. 结点插入
/* 新节点作为 x 节点的左孩子插入 */
BinNodePosi insertAsLC(BinNodePosi x, T const &e)
{
    _size ++;  //整体规模 +1
    x->insertAsLC(e);    // BinNode 结构体中的接口
    updateHeightAbove(x);    // x的历代祖先(包括x)的高度 *可能*增加,其余节点*必然不变*
  
    return  x->lchild;
}

/* 新节点作为 x 节点的右孩子插入 */
BinNodePosi insertAsRC(BinNodePosi x, T const &e)
{
    _size ++;  //整体规模 +1
    x->insertAsRC(e);    // BinNode 结构体中的接口
    updateHeightAbove(x);    // x的历代祖先(包括x)的高度 *可能*增加,其余节点*必然不变*
  
    return  x->rchild;
}


二叉树遍历算法实现

1. 先序遍历(Pre_order)
二叉树先序 :
  • 先根节点
  • 先序遍历根节点的左子树
  • 先序遍历根节点的右子树

遍历顺序 : 节点 --- 左孩子 --- 右孩子

  • 1.1 递归实现二叉树先序遍历算法

补上递归实现的图解

/* 递归实现*/
void traversePre(BinNodePosi x)
{
    if (NULL == x)       //递归出口
    {
        return;
    }

    Visit(x);                    // Visit()为访问节点数据函数
    traversePre(x->lchild);      //先序遍历左子树
    traversePre(x->rchild);      //先序遍历右子树

}
  • 1.2 非递归实现二叉树先序遍历算法 --- "实现1"

补上非递归实现方式1的图解

/* 非递归实现 code 1 */

  • 1.3 非递归实现二叉树先序遍历算法 --- "实现2"

补上非递归实现方式2的图解

/* 非递归实现 code 2 */


2. 中序遍历(In_order)
二叉树中序 :
  • 中序遍历根节点的左子树
  • 访问根节点
  • 中序遍历根节点的右子树

遍历顺序 : 左孩子 --- 节点 --- 右孩子

  • 2.1 递归实现二叉树中序遍历算法

补上递归实现方式的图解

/* 递归实现 code */

  • 2.2 非递归实现二叉树中序遍历算法

补上非递归实现方式的图解

/* 非递归实现 code 1 */


3. 后序遍历(Post_order)
二叉树后序 :
  • 后序遍历根节点的左子树
  • 后序遍历根节点的右子树
  • 访问根节点

遍历顺序 : 左孩子 --- 右孩子 --- 节点

  • 3.1 递归实现二叉树后序遍历算法

补上递归实现方式的图解

/* 递归实现 code */

  • 3.2 非递归实现二叉树后序遍历算法

补上非递归实现方式的图解

/* 非递归实现 code */


4. 层次遍历 (广度遍历)


5. 补充

对于二叉树,树的遍历通常就以上四种:先序遍历、中序遍历、后序遍历、广度优先遍历。(前三种亦统称深度优先遍历)
对于多叉树,树的遍历通常有两种:深度优先遍历、广度优先遍历。
这里补上之后整理的多叉树的深度和广度遍历链接



二叉树的重构

已知某二叉树的遍历序列,如何重构?条件是什么?

  • 任一二叉树 : 三种遍历序列(Pre, In, Post)
  • 已知 [ 先序 / 后序 ] + 中序,即可重构一棵二叉树

[分析]
只靠 先序 + 后序,当出现子树为空的情况,无法判断子树是 L or R,造成分歧。

但是在一种情况下, 先序 + 后序 可构造出唯一对应的二叉树。

  • [ 先序 + 后序 + 真二叉树 ]

真二叉树 : 分叉数为偶数个(0,2)



补充:二叉树的几种分类
  1. 真二叉树:所有节点的度不为1,即叶子节点的度为0,其他节点的度为2

  2. 完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树

  3. 满二叉树:完全二叉树的一种特殊情况,所有叶节点同处于最底层,每一层的节点数都达到饱和,称为满二叉树



二叉树的应用

1. 二叉树的深度 : "输入根节点,求该树的深度"
2. 输入二叉树的根节点,判断其是否是平衡二叉树

判断某一节点是否平衡的标准 : 其左右子树的深度之差的绝对值是否不大于 1
判断一棵二叉树是否平衡 : 其所有节点是否平衡

3. BST面试题1(from 《剑指offer》27):二叉搜索树和双向链表
4. BST面试题2(from 《剑指offer》50):树中两个节点的最低公共祖先

相关文章

  • 2. 二叉树 BinTree

    二叉树的实现 BinNode : 二叉树结点 二叉树结点结构代码 : 二叉树常用接口实现 将新结点作为左/右孩子插...

  • 12.树Tree(2)

    目录:1.二叉树的基本概念2.二叉树的性质3.二叉树的创建4.二叉树的遍历 1.二叉树的基本概念 2.二叉树的性质...

  • 二叉树的前中后序遍历 Java递归与非递归实现

    1. 二叉树的定义 构造二叉树 2. 二叉树的递归遍历 2.1 二叉树递归先序遍历 2.2 二叉树递归中序遍历 2...

  • 数据结构学习笔记

    1. 树,森林,二叉树之间的转换 树转换为二叉树 森林转为二叉树 二叉树转为树 二叉树转为森林 2. 哈弗曼树

  • python遍历二叉树

    定义二叉树: 构建二叉树: BFS: 先序遍历:1.递归版本: 2.非递归版本: 中序遍历: 1.递归版本 2.非...

  • 二叉树高频面试题和答案

    先上二叉树的数据结构: 二叉树的题目普遍可以用递归和迭代的方式来解 1. 求二叉树的最大深度 2. 求二叉树的最小...

  • 2.常用算法数据结构编程-二叉树子系统

    流程 1.创建二叉树的结构体节点2.创建一颗二叉树3.就是显示二叉树,求关于二叉树的相关数据(先序遍历,中序遍历,...

  • 二叉树与图

    二叉树深度搜索 1. 路径总和 II 前序操作和后序操作结合: 2.二叉树的最近公共祖先 3. 二叉树展开为链表...

  • 数据结构_知识点_二叉树

    1. 二叉树 (1) 可以为空,即n = 0(2) 左右有序,颠倒后是不同的树 2.特殊二叉树 (1)满二叉树(每...

  • 二叉树

    1.二叉树的遍历:前序、中序、后序遍历 2.二叉树查找节点和删除节点的代码

网友评论

      本文标题:2. 二叉树 BinTree

      本文链接:https://www.haomeiwen.com/subject/mgeksftx.html