//
//文件名称:BinaryTreeNode.h
//功能描述:
//版本说明:BinaryTreeNode API
//
//编写作者:2012.02.21 yanfeng.hu QQ:398303171@qq.com WX:windgs
//
//修改情况:完成基本功能搭建 V1.0.0
//
//
/*
最近在温习mysql的设计架构原理和详解的时候,又重新温习了一遍索引的设计,涉及到了B-树、B+-树、T-树等一些算法,这些都是大学的时候学习过,07年参加工作后就没有怎么太涉及,因为从事C++研发游戏项目
使用的都是C++标准库STL中的各种容器和各种算法,真正自己写的并不多,所以还是想自己掌握下里面的算法,提升一下自己的技术,做技术的千万不能懒,学到手里都是活~~~~~
一、二叉树概念
在大学的时候计算机书籍中已经接触,二叉树是每个结点有左右两个孩子的树形结构。因为都是面向对象的思想,所以可以在生活实践中结合很多场景设计进去。通常可以把孩子结点,叫做”左结点“和”右结点“
由左结点和右结点他们自己也构成了有个二叉树。二叉树是递归定义的,所以左右的孩子次序是固定的,不能颠倒,但是有些也采用非递归算法。
二、二叉排序树
二叉排序树又叫二叉查找树或者二叉搜索树,必须满足下面的条件:
1)若左子树不空,则左子树上所有结点的值均小于它的父结点的值;
2)若右子树不空,则右子树上所有结点的值均大于它的父结点的值
3)左、右子树也分别为二叉排序树
4)不存在键值相等的节点。(具体原因不详,可能是想mqp一样,不允许存在相同的key)
三、二叉树结点包含四个固定的成员
1)结点的数据域
2)指向父结点的指针域
3)指向左子结点的指针域
4)指向右子结点的指针域
结点的数据域、指向父结点的指针域从TreeNode模板类继承而来。
下面主要看算法和具体实现代码。
*/
//根据指针调用Release接口
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(x) if((x)!=NULL) { (x)->Release(); (x)=NULL; }
#endif//SAFE_RELEASE
#
template<typename T>
class TreeNode
{
protected:
int m_nValue; //具体结点的数值
TreeNode<T>* m_pParentNode; //父结点指针
}
///二叉树
template<typename T>
class BinaryTreeNode : public TreeNode<T>
{
public:
//构造函数
BinaryTreeNode()
{
m_pLeftNode = NULL;
m_pRightNode = NULL;
}
//析构函数
virtual ~BinaryTreeNode()
{
}
protected:
BinaryTreeNode<T>* m_pLeftNode; //左结点指针
BinaryTreeNode<T>* m_pRightNode; //右结点指针
public:
//工厂方法-创建二叉树-排序树-static fuction
static BinaryTreeNode<T>* CreateNew()
{
BinaryTreeNode<T>* pNewTreeNode = new BinaryTreeNode<T>();
if (!pNewTreeNode)
{
return NULL;
}
return pNewTreeNode;
}
//释放资源
virtual bool Release()
{
delete this;
return TRUE;
}
//
/*
* 根据具体值从根节点查找元素
* 参数
* nValue 具体结点的数值
* 返回值
* BinaryTreeNode<T>* 二叉树节点
*/
virtual BinaryTreeNode<T>* Find(const T& nValue) const
{
return Find(Root(), nValue);
}
//
/*
* 根据具体值从根节点查找元素
* 参数
* pTreeNode 开始查找的节点
* nValue 具体结点的数值
* 返回值
* BinaryTreeNode<T>* 二叉树节点
*/
virtual BinaryTreeNode<T>* Find(BinaryTreeNode<T>* pTreeNode, const T& nValue)const
{
BinaryTreeNode<T>* pRetNode = NULL;
//如果是根节点node
if (pTreeNode != NULL)
{
if (pTreeNode->m_nValue == nValue)
{
pRetNode = pTreeNode;
}
else
{
//查找左子树
if (pRetNode == NULL)
{
//查找其左子树
pRetNode = Find(pTreeNode->m_pLeftNode);
}
//如果左子树没有找到,查找右子树
if (pRetNode == NULL)
{
pRetNode = Find(pTreeNode->m_pRightNode);
}
}
}
return pRetNode;
}
//
/*
* 根据具体结点从根节点查找元素
* 参数
* nValue 具体结点的数值
* 返回值
* BinaryTreeNode<T>* 二叉树节点
*/
virtual BinaryTreeNode<T>* Find(const BinaryTreeNode<T>* pObjNode) const
{
return Find(root(), dynamic_caset< BinaryTreeNode<T>* >(pObjNode));
}
//
/*
* 基于结点的查找
* 参数
* pTreeNode 开始查找的节点
* nValue 具体结点的数值
* 返回值
* BinaryTreeNode<T>* 二叉树节点
*/
virtual BinaryTreeNode<T>* Find(BinaryTreeNode<T>* pTreeNode, const BinaryTreeNode<T>* pObjNode)const
{
BinaryTreeNode<T>* pRetNode = NULL;
if (pTreeNode != NULL)
{
//如果是根结点,则直接返回根结点
if (pTreeNode == pObjNode)
{
pRetNode = pTreeNode;
}
else //不是跟结点
{
//查找左结点
if (pRetNode == NULL)
{
pRetNode = Find(pTreeNode->m_pLeftNode);
}
//如果左结点没有找到,则直接找右结点
if (pRetNode == NULL)
{
pRetNode = Find(pTreeNode->m_pRightNode);
}
}
}
return pRetNode;
}
//
/*
* 结点插入类型enum
*/
enum BTInsertType
{
BTIT_ANY,
BTIT_LEFT,
BTIT_RIGHT
};
//
/*
* 插入结点根据类型
* 参数
* pNewTreeNode 准备插入的新节点
* pTreeNode 具体结点
* type 具体的插入类型
* 返回值
* 成功返回true 失败返回false
*/
virtual bool Insert(BinaryTreeNode<T>* pNewTreeNode, BinaryTreeNode<T>* pTreeNode, BTInsertType type)
{
bool ret = true;
if (type == BTInsertType::BTIT_ANY) //插入位置为any
{
if (pTreeNode->m_pLeftNode == NULL) //左结点为空则插入做结点
{
pTreeNode->m_pLeftNode = pNewTreeNode;
}
else if (pTreeNode->m_pRightNode == NULL) //右结点为空则插入右结点
{
pTreeNode->m_pRightNode = pNewTreeNode;
}
else //如果左右结点都不为空,则插入失败
{
ret = false;
}
}
else if (type == BTInsertType::BTIT_LEFT) //插入左结点
{
if (pTreeNode->m_pLeftNode == NULL) //左结点为空则设置左结点
{
pTreeNode->m_pLeftNode = pNewTreeNode;
}
else //不为空
{
ret = false;
}
}
else if (type == BTInsertType::BTIT_RIGHT) //插入右结点
{
if (pTreeNode->m_pRightNode == NULL) //右结点为空则设置右结点
{
pTreeNode->m_pRightNode = pNewTreeNode;
}
else //不为空
{
ret = false;
}
}
else
{
ret = false;
}
return ret;
}
//
/*
* 插入新结点,没有位置要求
* 参数
* pNewTreeNode 准备插入的新节点
* 返回值
* 成功返回true 失败返回false
*/
virtual bool Insert(BinaryTreeNode<T>* pNewTreeNode)
{
return Insert(dynamic_caset< BinaryTreeNode<T>* >(pNewTreeNode), BTInsertType::BTIT_ANY);
}
//
/*
* 插入结点,指定插入位置
* 参数
* pNewTreeNode 准备插入的新节点
* pTreeNode 具体结点
* type 具体的插入类型
* 返回值
* 成功返回true 失败返回false
*/
virtual bool Insert(BinaryTreeNode<T>* pTreeNode, BTInsertType type)
{
bool ret = true;
if (pTreeNode != NULL)
{
if (pTreeNode->m_pRoot == NULL)
{
pTreeNode->m_pParentNode = pTreeNode;
}
else
{
BinaryTreeNode<T>* pNode = Find(pTreeNode->m_pParentNode);
if (pNode != NULL)
{
ret = Insert(dynamic_caset<BinaryTreeNode<T>*>(pTreeNode), pNode, type);
}
else
{
LOGERROR("Parameter invalid...");
}
}
}
else
{
LOGERROR("Parameter invalid...");
}
return ret;
}
//
/*
* 插入结点,指定插入位置和父节点
* 参数
* nValue 插入的值
* pParentTreeNode 父结点
* type 插入类型
* 返回值
* 成功返回true 失败返回false
*/
virtual bool Insert(const T& nValue, BinaryTreeNode<T>* pParentTreeNode, BTInsertType type)
{
bool ret = true;
BinaryTreeNode<T>* pNewTreeNode = BinaryTreeNode<T>::CreateNew();
if (pNewTreeNode != NULL)
{
pNewTreeNode->m_pParentNode = pParentTreeNode;
pNewTreeNode->m_nValue = nValue;
ret = Insert(pNewTreeNode, type);
if (!ret)
{
SAFE_RELEASE(pNewTreeNode);
}
}
else
{
LOGERROR("No enough memory...");
}
return ret;
}
//
/*
* 插入结点,指定父节点
* 参数
* nValue 插入的值
* pParentTreeNode 父结点
* type 插入类型
* 返回值
* 成功返回true 失败返回false
*/
virtual bool Insert(const T& nValue, BinaryTreeNode<T>* pParentTreeNode)
{
return Insert(nValue, pParentTreeNode, BTInsertType::BTIT_ANY);
}
//
/*
* 删除结点
* 参数
* pDelTreeNode 待删除的结点
* pRetTreeNode 父结点
* type 插入类型
* 返回值
* 无
*/
virtual void Remove(BinaryTreeNode<T>* pDelTreeNode, BinaryTreeNode<T>* pRetTreeNode)
{
pRetTreeNode = new BTree<T>();
if (!pRetTreeNode)
{
LOGERROR("No enough memory...");
return false;
}
else
{
if (pDelTreeNode == Root())
{
this->m_pRoot = NULL;
}
else
{
BinaryTreeNode<T>* pParentTreeNode = dynamic_caset<BinaryTreeNode<T>*>(pDelTreeNode->m_pParentNode);
if (pParentTreeNode && pParentTreeNode->m_pLeftNode == pDelTreeNode)
{
pParentTreeNode->m_pLeftNode = NULL;
}
else if (pParentTreeNode && pParentTreeNode->m_pLeftNode == pDelTreeNode)
{
pParentTreeNode->m_pRightNode = NULL;
}
pDelTreeNode->m_pParentNode = NULL;
}
pRetTreeNode->m_pRoot = pDelTreeNode;
}
}
//
/*
* 根据值删除结点
* 参数
* nValue 值
* 返回值
* BTree<T>*
*/
virtual BTree<T>* Remove(const T& nValue)
{
BTree<T>* ret = NULL;
BinaryTreeNode<T>* pTreeNode = Find(nValue);
if (pTreeNode == NULL)
{
LOGERROR("No value...");
}
else
{
Remove(pTreeNode, ret);
}
return ret;
}
//
/*
* 根据结点删除
* 参数
* pTreeNode 待删除的结点
* 返回值
* BTree<T>*
*/
virtual BTree<T>* Remove(BinaryTreeNode<T>* pTreeNode)
{
BTree<T>* ret = NULL;
BinaryTreeNode<T>* pTreeNode = Find(nValue);
if (pTreeNode == NULL)
{
LOGERROR("No value...");
}
else
{
Remove(dynamic_caset<BinaryTreeNode<T>*>(pTreeNode), ret);
}
return ret;
}
}
总结
最近时间稍微充裕了一点,所以整理的一些二叉树相关的算法,算法资料和思想,如有错误,欢迎指正!后续如果有新的算法,我也会更新进去