真c++ 从二叉树到红黑树(2)之二叉树基类
此文章为从二叉树到红黑树系列文章的第二节,主要介绍介绍二叉树抽象基类的基本组成。为后续BST,AVL和RedBlack做好铺垫
文章目录
- 一、前面文章链接~(点击右边波浪线可以返回目录)
- 二、二叉树抽象基类~
- (一)定义变量和接口~
- 1.需要的变量~
- 2.需要的接口~
- 3.重要辅助函数~
- 4.其他辅助函数~
- 5.BinTree.h~
- (二)获取当前节点的父亲的孩子的引用~
- (三)更新当前节点的高度~
- (四)更新当前节点及其祖先节点的高度~
- (五)删除函数~
- (六)release.h头文件~
- (七)完整BinTree.h~
- 三、后序文章链接~
一、前面文章链接~(点击右边波浪线可以返回目录)
在阅读本文前,强烈建议你看下前面的文章的目录、前言以及基本介绍,否则你无法理解后面的内容。链接如下:
- 基本二叉树节点,通用函数 二叉树节点
二、二叉树抽象基类~
(一)定义变量和接口~
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
三、后序文章链接~
- 基本二叉树节点,通用函数 二叉树节点
- 基本二叉树类的定义和实现 二叉树基类
- BST(二叉搜索树的实现) BST
- AVL(二叉平衡搜索树的实现)AVL
- B树的实现(如果你只想了解B树,可以跳过所有章节,直接看B树)B树
- 红黑树的实现 RedBlack
学一个东西,不知道其道理,不高明!
真c++ 从二叉树到红黑树(2)之二叉树基类相关推荐
- 真c++ 从二叉树到红黑树(6)之红黑树RedBlack
此文章为从二叉树到红黑树系列文章的第六节,主要介绍介绍红黑树,相信,有了之前BST,AVL和B树的铺垫,你会很快地理解红黑树.但红黑树的情况也十分复杂,因此,推荐分两天来看红黑树.一天看插入,一天 ...
- 真c++ 从二叉树到红黑树(4)之二叉平衡搜索树AVL
此文章为从二叉树到红黑树系列文章的第四节,主要介绍介绍二叉平衡搜索树AVL,当你理解了AVL,红黑树你就理解了一半了! 文章目录 一.前面文章链接~(点击右边波浪线可以返回目录) 二.由BST引入 ...
- 真c++ 从二叉树到红黑树(3)之二叉搜索树BST
此文章为从二叉树到红黑树系列文章的第三节,主要介绍介绍二叉搜索树BST,为AVL和RedBlack打下基础 文章目录 一.前面文章链接~(点击右边波浪线可以返回目录) 二.二叉搜索树BST的定义~ ...
- 真c++ 从二叉树到红黑树(1)之二叉树节点类及遍历详解
此文章为从二叉树到红黑树系列文章的第一节,主要介绍写这系列文章的起因,致谢邓老师,解释二叉树节点类和二叉树的四种遍历写法(包括递归和迭代写法) 文章目录 一.前言与致谢~(点击右边波浪线可以返回目 ...
- 2022年3月28日记:Linux服务器开发,二叉树与红黑树
──────────────────────────────────── ┌------------┐ │▉▉♥♥♥♥♥♥♥♥ 99% │ ♥❤ 鱼沈雁杳天涯路,始信人间别离苦. └--------- ...
- 二叉树 平衡二叉树 红黑树_迅捷树,二叉树
二叉树 平衡二叉树 红黑树 In this tutorial, we'll be discussing the Data Structure Trees and implement it using ...
- 【Mysql索引】二叉树、红黑树、B树、B+树
[Mysql索引]二叉树.红黑树.B树.B+树 (1)哈希表 (2)二叉树的弊端的演示: (3)红黑树的插入演示: (4)B树的演示 (5)B+树的演示(叶子加指针:支持范围查找) (5.1)借着学习 ...
- MySQL索引数据结构二叉树、红黑树、B-Tree、B+Tree、Hash
索引:帮助MySQL高效获取数据的有序的数据结构. 假设我们有一张表table,包含Clo1和Clo2两个字段 内存地址 Clo1 Clo2 0x07 1 36 0x5A 2 20 0x7A 3 80 ...
- 数据结构(三):非线性逻辑结构-特殊的二叉树结构:堆、哈夫曼树、二叉搜索树、平衡二叉搜索树、红黑树、线索二叉树
在上一篇数据结构的博文<数据结构(三):非线性逻辑结构-二叉树>中已经对二叉树的概念.遍历等基本的概念和操作进行了介绍.本篇博文主要介绍几个特殊的二叉树,堆.哈夫曼树.二叉搜索树.平衡二叉 ...
最新文章
- 使用DCloud+Framework7制作移动APP应用(一)
- 利用ansible 自动发布安装
- Jmock 原理简单说明
- 阿里为什么禁用Executors创建线程池?
- 十大网络安全策略 打造坚固的内网
- Angular服务器端渲染
- #蓝桥杯嵌入式#电路模电基础知识
- c语言旋转led时钟设计报告,《基于单片机的LED旋转时钟设计报告》.doc
- 66个求职应聘技巧性问答(六)
- 未解——Matlab积分运算int函数
- 一文看懂多模态大型语言模型GPT-4
- 无抵押贷款 幸福生活新选择
- 数据结构与算法实验6——图论 7-10 公路村村通
- 洛谷P1080 [NOIP2012 提高组] 国王游戏(贪心,高精度)
- 屏幕长度与像素长度的转换
- 2019, XII Samara Regional Intercollegiate Programming Contest 全部题解
- OpenCV4学习笔记(23)——几何矩、中心矩、归一化矩和Hu矩的计算,以及基于Hu矩的轮廓匹配
- 苹果系统引导修复工具_苹果客服渠道回应 iPhone 12 系列屏幕 “发绿”情况:将在新系统中修复...
- 日本网红摩托车小姐姐,居然是50岁中年大叔
- 雅马哈与上位机TCP通讯
热门文章
- linux升级wine1.7,Wine 1.7.55 发布下载
- C语言编程>第十三周 ⑧ 已知学生的记录由学号和学习成绩组成,M名学生的数据已存入stu结构体数组中。请编写函数fun,该函数的功能是:
- js 毫秒 微秒 转为 时分秒
- 计算机是如何工作的? ----李泽源
- 用VSCODE看linux内核代码
- OpenCV第五章练习p163_5~8
- 7月5号cf服务器维护,cf2015年5月7日维护到几点 cf5月7日更新公告
- 计算机视觉基础-图像处理-几何变换
- c语言setfocus作用,C语言FindWindow和SetFocus的问题?
- C语言-快速回忆_float和double的输入输出格式