真c++ 从二叉树到红黑树(2)之二叉树基类
生活随笔
收集整理的這篇文章主要介紹了
真c++ 从二叉树到红黑树(2)之二叉树基类
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
??此文章為從二叉樹到紅黑樹系列文章的第二節,主要介紹介紹二叉樹抽象基類的基本組成。為后續BST,AVL和RedBlack做好鋪墊
文章目錄
- 一、前面文章鏈接~(點擊右邊波浪線可以返回目錄)
- 二、二叉樹抽象基類~
- (一)定義變量和接口~
- 1.需要的變量~
- 2.需要的接口~
- 3.重要輔助函數~
- 4.其他輔助函數~
- 5.BinTree.h~
- (二)獲取當前節點的父親的孩子的引用~
- (三)更新當前節點的高度~
- (四)更新當前節點及其祖先節點的高度~
- (五)刪除函數~
- (六)release.h頭文件~
- (七)完整BinTree.h~
- 三、后序文章鏈接~
一、前面文章鏈接~(點擊右邊波浪線可以返回目錄)
??在閱讀本文前,強烈建議你看下前面的文章的目錄、前言以及基本介紹,否則你無法理解后面的內容。鏈接如下:
二、二叉樹抽象基類~
(一)定義變量和接口~
1.需要的變量~
int _size;//二叉樹的規模 BinNodePtr _root;//二叉樹的樹根2.需要的接口~
構造,析構 判空 獲取二叉樹的規模、根節點 獲取二叉樹當前高度 四種遍歷(結合根節點使用)3.重要輔助函數~
獲取當前節點的父親的孩子的引用。(這句話有點拗口,但這個函數是整個流程的關鍵) FromParentTo4.其他輔助函數~
更新節點的高度 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三、后序文章鏈接~
學一個東西,不知道其道理,不高明!
總結
以上是生活随笔為你收集整理的真c++ 从二叉树到红黑树(2)之二叉树基类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【图解算法面试】记一次面试:说说游戏中的
- 下一篇: 高仿微信登入界面