红黑树

这里主要讲解红黑树的源码实现,并附上源码。具体参考书籍为《算法导论》

首先,我们知道红黑树也是树的一种,所以在程序的设计上,它的大部分方法完全能够继承自普通树(父类)的方法,父类的存在可以使得在对树这种数据结构了解的同时,同时也注意程序的高聚合与低耦合性。原先在对二叉树与红黑树数据结构实现的时候,都是分为一个二叉树实现类,一个红黑树实现类,两个类中,往往好多方法都是重用,以至于这里copy过去,那里从copy过来,完全没注意聚合与耦合的问题。大神就略过,希望能够对你编程规范有一定帮助。
环境为VS2015

1、父类的实现 CTree

#pragma once
#include <iostream>
#include <map>
#include <list>
#include <queue>
using namespace std;

/************************************************************************/
/* 普通树(父类) 包含一些树节点的定义和通用方法                        */
/************************************************************************/

enum ColorType
{
    RED,
    BLACK,
};

struct NODE
{
    int key;
    NODE *pLeft;
    NODE *pRight;
    NODE *pParent;
    ColorType color;
};

struct CHILDNUM
{
    int nLeftNum;
    int nRightNum;
    int totalSpace;// 空格数
};

class CTree
{
public:
    CTree();
    ~CTree();

    virtual void MakeTree(int *pAry, int nLen);             // 使用数组生成树结构
    virtual void TreeInsert(int key) = 0;                   // 插入数据节点(普通二叉树插入方法)
    virtual NODE* SearchNode(int nValue);                   // 根据值查找目标节点
    virtual int GetTreeHeight(NODE *pNode);                 // 获取树的高度
    NODE* GetRootNode() const;                              // 获取根节点
    void PrintTree();                                       // 打印成树形(类似层序遍历)

    NODE *m_pRoot;                                          // 根节点
    bool m_bInitRoot;                                       // 根节点是否初始化
private:
    void GetChildNum(NODE *pNode, int &nNum);               // 获取子节点的个数(采用前序遍历的方式)
    void GetChildNumToMap(NODE *pNode);                     // 计算每个子节点的个数,并存储到map结构中(使用前序遍历获取每个节点的子节点个数并存储到map中)
    void PrintSingleNode(NODE *pNode, int &nOffset);        // 打印一行树
    void PrintSpace(int nSpace, int key, int &nOffset);     // 打印空格

    NODE* TreeSearch(NODE *pNode, int value);               // 查询二叉搜索树(递归算法)

    map<NODE*, CHILDNUM> m_Map;                             // 记录每个节点的子节点个数
};

提供给外部的接口均是一些插入、生成树结构、查找某个key对应的目标节点,以及打印树结构等普通树的公共方法,而主要的实现封装在私有成员函数中,比如打印树中设计到的打印空格与打印行数。
而为什么父类的成员函数要使用virtual关键字,当然是为了实现类的多态。也方便后期实现一个树的工厂方法,达到通过一个工厂方法进行对不同树对象的操作。如果不懂工厂方法,可以留言我再加上,也很简单。

2、二叉树的简单实现 CBinaryTree

#pragma once
#include "Tree.h"

/************************************************************************/
/* 二叉树                                                                     */
/************************************************************************/

class CBinaryTree : public CTree
{
public:
    CBinaryTree();
    ~CBinaryTree();

    virtual void TreeInsert(int key) override;// 数据插入生成树结构

private:
    void BinaryTreeInsert(NODE* &pNode, NODE *pNewNode);    // 插入数据节点(普通二叉树插入方法)
};

父类CTree中,对TreeInsert的实现是纯虚函数,所以这里需要子类继承实现。

3、红黑树的简单实现 CRBTree

#pragma once
#include "Tree.h"

/************************************************************************/
/* 红黑树                                                                     */
/************************************************************************/

class CRBTree : public CTree
{
public:
    CRBTree();
    ~CRBTree();

    virtual void TreeInsert(int key) override;

private:
    void RB_INSERT_FIXUP(NODE* &pRoot, NODE *pNowNode);// 使得新的节点加入后依旧保持红黑树性质
    void LeftRotate(NODE* &pRoot, NODE *pNode);// 左旋转
    void RightRotate(NODE* &pRoot, NODE *pNode);// 右旋转

    void RBTreeInsert(NODE *pNewNode);// 重写插入算法(红黑树树插入方法)
};

小结:通过对父类CTree的继承,不仅仅可以简单看出二叉树与红黑树的差别,也省去了很多冗余的方法。通过对树的学习,我们可以了解map的基本实现原理,如果这里使用模板来实现就更好了。
类的具体是实现源码地址:https://download.csdn.net/download/qq_30145355/10525848

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值