此文章为从二叉树到红黑树系列文章的第二节,主要介绍介绍二叉树抽象基类的基本组成。为后续BST,AVL和RedBlack做好铺垫

文章目录

  • 一、前面文章链接~(点击右边波浪线可以返回目录)
  • 二、二叉树抽象基类~
    • (一)定义变量和接口~
      • 1.需要的变量~
      • 2.需要的接口~
      • 3.重要辅助函数~
      • 4.其他辅助函数~
      • 5.BinTree.h~
    • (二)获取当前节点的父亲的孩子的引用~
    • (三)更新当前节点的高度~
    • (四)更新当前节点及其祖先节点的高度~
    • (五)删除函数~
    • (六)release.h头文件~
    • (七)完整BinTree.h~
  • 三、后序文章链接~

一、前面文章链接~(点击右边波浪线可以返回目录)

  在阅读本文前,强烈建议你看下前面的文章的目录、前言以及基本介绍,否则你无法理解后面的内容。链接如下:

  1. 基本二叉树节点,通用函数 二叉树节点

二、二叉树抽象基类~

(一)定义变量和接口~

1.需要的变量~

int _size;//二叉树的规模
BinNodePtr _root;//二叉树的树根

2.需要的接口~

构造,析构
判空
获取二叉树的规模、根节点
获取二叉树当前高度
四种遍历(结合根节点使用)

3.重要辅助函数~

获取当前节点的父亲的孩子的引用。(这句话有点拗口,但这个函数是整个流程的关键)
FromParentTo

4.其他辅助函数~

更新节点的高度 updateHeight
更新节点以及其祖先的高度 updateHeightAbove
删除所有节点 remove
插入节点insert(为了方便起见,设为纯虚函数,使这个二叉树基类不能实例化)

5.BinTree.h~

template<typename T=int>
class BinTree {protected:using BinNodePtr = BinNode<T>*;using BinTreePtr = BinTree<T>*;protected:int _size;//二叉树的规模BinNodePtr _root;//二叉树的树根public:BinTree() :_size(0), _root(nullptr) {}virtual ~BinTree() {//std::cout << "调用析构函数" << std::endl;if (0 < _size)remove(_root); }public:constexpr int size()const { return _size; }//规模constexpr bool empty()const { return !_root; }//判空inline BinNodePtr root()const {//返回树根return (_root) ? _root : nullptr;}constexpr int getHeight()const {//获取树高度return (this->_root) ? this->_root->_height : -1;}public:template<typename VST>//层次遍历void travLevel(VST visit) {if (_root)_root->travLevel(visit);}template<typename VST>//先序遍历void travPre(VST visit,const int&method=1) {if (_root)_root->travPre(visit, method);}template<typename VST>//中序遍历void travIn(VST visit, const int& method = 1) {if (_root)_root->travIn(visit, method);}template<typename VST>//后序遍历void travPost(VST visit, const int& method = 1) {if (_root)_root->travPost(visit, method);}protected:virtual int updateHeight(BinNodePtr x)const;//更新节点x的高度/*vs开最新版本的c++就可以用virtual constexpr*/void updateHeightAbove(BinNodePtr x)const;//更新节点x及其祖先的高度protected://注意返回值为引用,不然无法作为左值BinNodePtr& FromParentTo(BinNodePtr x) {/*用这个更改x的父亲的左右孩子*//*接受者一般要加个引用接收*/return   (IsRoot(x) ? this->_root : (IsLChild(x) ? x->_parent->_lchild : x->_parent->_rchild));}protected:virtual BinNode<T>* insert(const T& data) = 0;//插入节点,为了方便起见,设为纯虚函数,即这个基类为抽象类,没有实例private:void remove(BinNodePtr x);//只用于析构函数,因此不管高度等其他因素,直接暴力全部删除};//class BinTree

(二)获取当前节点的父亲的孩子的引用~

  这个函数对于AVL树和RedBlack树的插入和删除而言,至关重要。我会在AVL和RedBlack树的相应部分再次说明这个函数的作用。

//注意返回值为引用,不然无法作为左值
BinNodePtr& FromParentTo(BinNodePtr x) {/*用这个更改x的父亲的左右孩子*//*接受者一般要加个引用接收*/return   (IsRoot(x) ? this->_root : (IsLChild(x) ? x->_parent->_lchild : x->_parent->_rchild));
}

(三)更新当前节点的高度~

此处stature是本系列文章第一节的在全局区定义的函数,头文件为BInNode_Macro.h。

//更新节点x的高度
template<typename T>
int BinTree<T>::updateHeight(BinNodePtr x)const {//高度为左右子树的高度的最大值return x->_height = 1 + std::max(stature(x->_lchild), stature(x->_rchild));
}

(四)更新当前节点及其祖先节点的高度~

  通常,还需要从当前节点出发沿parent指针逆行向上,依次更新各代祖先的高度记录,直到这个祖先的高度不变时停止。

//更新节点x及其祖先的高度
template<typename T>
void BinTree<T>::updateHeightAbove(BinNodePtr x)const{if (x == nullptr)return;updateHeight(x);do {x = x->_parent;if (x == nullptr)//如果父节点为空节点,则返回return;int currentHeight = x->_height;//记录节点当前的高度int afterHeight = updateHeight(x);if (currentHeight == afterHeight)//只要其高度没有更新,那么就可以跳出循环break;} while (x);//当此节点不为空
}

(五)删除函数~

这个函数用于析构函数中,用于所有树的析构,无论是BST,AVL还是RedBlack。

//=========删除============//
template<typename T>
void BinTree<T>::remove(BinNodePtr x) {if (nullptr==x)return;remove(x->_lchild);remove(x->_rchild);/*处于方便,用递归删除*/release(x->_data);release(x);
}

(六)release.h头文件~

  在(五)中的删除代码中,可以看到用到了release函数来进行节点的删除,其位于头文件release.h中。

该删除函数用到了模板偏特化技术。

#pragma oncetemplate<typename T>
struct Cleaner {static void clean(T& x) {#ifdef DEBUGprintf("删除了\n");
#endif // DEBUG}
};template<typename T>
struct Cleaner<T*> {static void clean(T*& x) {//注意这里是引用,方便删除后,直接变成空指针if (x) {delete x;x = nullptr;}}
};template<typename T>
static void release(T &x) {//利用模板偏特化,删除节点,若为指针,则delete,若不为指针,则不做任何操作。Cleaner<T>::clean(x);
}

(七)完整BinTree.h~

#pragma once
#include"BinNode.h"
#include "release.h"namespace mytree {using namespace mytree_marcro;template<typename T=int>class BinTree {protected:using BinNodePtr = BinNode<T>*;using BinTreePtr = BinTree<T>*;protected:int _size;//二叉树的规模BinNodePtr _root;//二叉树的树根public:BinTree() :_size(0), _root(nullptr) {}virtual ~BinTree() {//std::cout << "调用析构函数" << std::endl;if (0 < _size)remove(_root); }public:constexpr int size()const { return _size; }//规模constexpr bool empty()const { return !_root; }//判空inline BinNodePtr root()const {//返回树根return (_root) ? _root : nullptr;}constexpr int getHeight()const {//获取树高度return (this->_root) ? this->_root->_height : -1;}public:template<typename VST>//层次遍历void travLevel(VST visit) {if (_root)_root->travLevel(visit);}template<typename VST>//先序遍历void travPre(VST visit,const int&method=1) {if (_root)_root->travPre(visit, method);}template<typename VST>//中序遍历void travIn(VST visit, const int& method = 1) {if (_root)_root->travIn(visit, method);}template<typename VST>//后序遍历void travPost(VST visit, const int& method = 1) {if (_root)_root->travPost(visit, method);}protected:virtual int updateHeight(BinNodePtr x)const;//更新节点x的高度/*vs开最新版本的c++就可以用virtual constexpr*/void updateHeightAbove(BinNodePtr x)const;//更新节点x及其祖先的高度protected://注意返回值为引用,不然无法作为左值BinNodePtr& FromParentTo(BinNodePtr x) {/*用这个更改x的父亲的左右孩子*//*接受者一般要加个引用接收*/return   (IsRoot(x) ? this->_root : (IsLChild(x) ? x->_parent->_lchild : x->_parent->_rchild));}protected:virtual BinNode<T>* insert(const T& data) = 0;//插入节点,为了方便起见,设为纯虚函数,即这个基类为抽象类,没有实例private:void remove(BinNodePtr x);//只用于析构函数,因此不管高度等其他因素,直接暴力全部删除};//class BinTree//================更新高度==================////更新节点x的高度template<typename T>int BinTree<T>::updateHeight(BinNodePtr x)const {return x->_height = 1 + std::max(stature(x->_lchild), stature(x->_rchild));//高度为左右子树的高度的最大值}//更新节点x及其祖先的高度template<typename T>void BinTree<T>::updateHeightAbove(BinNodePtr x)const{if (x == nullptr)return;updateHeight(x);do {x = x->_parent;if (x == nullptr)//如果父节点为空节点,则返回return;int currentHeight = x->_height;//记录节点当前的高度int afterHeight = updateHeight(x);if (currentHeight == afterHeight)//只要其高度没有更新,那么就可以跳出循环break;} while (x);//当此节点不为空}//=========删除============//template<typename T>void BinTree<T>::remove(BinNodePtr x) {if (nullptr==x)return;remove(x->_lchild);remove(x->_rchild);/*处于方便,用递归删除*/release(x->_data);release(x);}
}//namespace mytree

三、后序文章链接~

  1. 基本二叉树节点,通用函数 二叉树节点
  2. 基本二叉树类的定义和实现 二叉树基类
  3. BST(二叉搜索树的实现) BST
  4. AVL(二叉平衡搜索树的实现)AVL
  5. B树的实现(如果你只想了解B树,可以跳过所有章节,直接看B树)B树
  6. 红黑树的实现 RedBlack

学一个东西,不知道其道理,不高明!

真c++ 从二叉树到红黑树(2)之二叉树基类相关推荐

  1. 真c++ 从二叉树到红黑树(6)之红黑树RedBlack

      此文章为从二叉树到红黑树系列文章的第六节,主要介绍介绍红黑树,相信,有了之前BST,AVL和B树的铺垫,你会很快地理解红黑树.但红黑树的情况也十分复杂,因此,推荐分两天来看红黑树.一天看插入,一天 ...

  2. 真c++ 从二叉树到红黑树(4)之二叉平衡搜索树AVL

      此文章为从二叉树到红黑树系列文章的第四节,主要介绍介绍二叉平衡搜索树AVL,当你理解了AVL,红黑树你就理解了一半了! 文章目录 一.前面文章链接~(点击右边波浪线可以返回目录) 二.由BST引入 ...

  3. 真c++ 从二叉树到红黑树(3)之二叉搜索树BST

      此文章为从二叉树到红黑树系列文章的第三节,主要介绍介绍二叉搜索树BST,为AVL和RedBlack打下基础 文章目录 一.前面文章链接~(点击右边波浪线可以返回目录) 二.二叉搜索树BST的定义~ ...

  4. 真c++ 从二叉树到红黑树(1)之二叉树节点类及遍历详解

      此文章为从二叉树到红黑树系列文章的第一节,主要介绍写这系列文章的起因,致谢邓老师,解释二叉树节点类和二叉树的四种遍历写法(包括递归和迭代写法) 文章目录 一.前言与致谢~(点击右边波浪线可以返回目 ...

  5. 2022年3月28日记:Linux服务器开发,二叉树与红黑树

    ──────────────────────────────────── ┌------------┐ │▉▉♥♥♥♥♥♥♥♥ 99% │ ♥❤ 鱼沈雁杳天涯路,始信人间别离苦. └--------- ...

  6. 二叉树 平衡二叉树 红黑树_迅捷树,二叉树

    二叉树 平衡二叉树 红黑树 In this tutorial, we'll be discussing the Data Structure Trees and implement it using ...

  7. 【Mysql索引】二叉树、红黑树、B树、B+树

    [Mysql索引]二叉树.红黑树.B树.B+树 (1)哈希表 (2)二叉树的弊端的演示: (3)红黑树的插入演示: (4)B树的演示 (5)B+树的演示(叶子加指针:支持范围查找) (5.1)借着学习 ...

  8. MySQL索引数据结构二叉树、红黑树、B-Tree、B+Tree、Hash

    索引:帮助MySQL高效获取数据的有序的数据结构. 假设我们有一张表table,包含Clo1和Clo2两个字段 内存地址 Clo1 Clo2 0x07 1 36 0x5A 2 20 0x7A 3 80 ...

  9. 数据结构(三):非线性逻辑结构-特殊的二叉树结构:堆、哈夫曼树、二叉搜索树、平衡二叉搜索树、红黑树、线索二叉树

    在上一篇数据结构的博文<数据结构(三):非线性逻辑结构-二叉树>中已经对二叉树的概念.遍历等基本的概念和操作进行了介绍.本篇博文主要介绍几个特殊的二叉树,堆.哈夫曼树.二叉搜索树.平衡二叉 ...

最新文章

  1. 国际机器人联合会:全球工业机器人2019报告
  2. OWASP 2017 Top10 漏洞体系
  3. Linux下 WRF Domain Wizard 使用教程(PART1:下载+安装)
  4. python 将ipv4的格式转换
  5. 【数据结构与算法】之深入解析“水壶问题”的求解思路与算法示例
  6. win7卸载java_Win7彻底卸载Oracle 11g图文步骤(靠谱)
  7. PHP在线无人值守源码交易网站源码,集成支付宝微信接口
  8. java 类继承命名_Java 语言的类间的继承关系是( )。_学小易找答案
  9. nginx+thinkphp下解决不支持pathinfo模式以及存在的各种404,500问题
  10. LeetCode问题7
  11. bzoj 1617: [Usaco2008 Mar]River Crossing渡河问题(DP)
  12. 二相四线制步进电机驱动原理与Proteus仿真
  13. ASCII、 Unicode 和 UTF8
  14. 【数据集】Python爬取某国内所有航班记录
  15. C语言之数组的正向逆向输出
  16. Centos7 Springboot 启动脚本
  17. 计算机网络实验:CISCO IOS 路由器基本配置
  18. Amazon SageMaker简直就是机器学习平台的天花板
  19. 编译akm小车底盘控制节点
  20. 黑白棋出现pass 的条件 java_JAVA黑白棋之学习感悟

热门文章

  1. dz后台html,建立discuz后台管理页面的模板
  2. MacBook Pro16大小写键caps lock灯不亮的问题解决
  3. 新款趣味测试小程序源码/带流量主小程序源码
  4. 从FragmentPagerAdapter看Fragment 生命周期
  5. 解决问题记录4:kettle数据库连接报错时区问题
  6. 百度SEO快排系统都有哪些类别?【系统之间的区别】
  7. [转贴]去除迅雷广告和弹出广告窗口
  8. r5处理器_R5-4500U / R5-4600U笔记本推荐
  9. 2.ECMAScript6详解
  10. p4交换机模拟器bmv2的一些教程