目录
二叉树引言
通用树的结构过于复杂,工程中很少会用到这么复杂的树,该如何简化呢?→减少孩子结点数量→二叉树
通用树结构回顾
双亲孩子表示法:
每个结点都有一个指向其双亲的指针
每个结点都有若干个指向其孩子的指针
二叉树树结构引进
孩子兄弟表示法:
每个结点都有一个指向其第一个孩子的指针
每个结点都有一个指向其第一个右兄弟的指针
孩子兄弟表示法的特点
能够表示任意的树形结构
每个结点包含一个数据成员和两个指针成员
孩子结点指针和兄弟结点指针构成了“树杈”
二叉树的定义
二叉树由n(n >= 0)个结点组成的有限集合,该集合或者为空
或者由一个根结点加上两颗分别称为左子树和右子树的、互不相交的二叉树组成
特殊的二叉树
满二叉树:
如果二叉树所有分支结点的度数都为2
且叶节点都在同一层次上
则称这类二叉树为满二叉树
完全二叉树:
如果一棵具有n个结点的高度为k的二叉树
它的每一个结点都与高度为k的满二叉树中编号为1——n的结点一一对应
则这棵二叉树称为完全二叉树(从上到下,从左到右编号)
特点:
*同样结点数的二叉树,完全二叉树的高度最小
*完全二叉树的叶结点仅出现在最下面两层
-最底层的叶结点一定出现在左边
-倒数第二层的叶结点一定出现在右边
-完全二叉树中度为1的结点只有左孩子
二叉树的性质
性质1
二叉树的第 i 层最多有2^(i - 1)个结点(根结点为第一层)
性质2
高度为 k 的二叉树最多有2^(i - 1)个结点
性质3
对任何一棵二叉树,如果其叶结点有 n0 个,度为2的非叶结点有 n2 个,则有 n0 = n2 + 1
证明:
假设二叉树中度为1的结点有 n1 个且总结点为 n 个
则: n = n0 + n1 + n2
假设二叉树中父节点与子结点间的边为 e 条
则: e = n1 + 2 * n2 = n - 1
所以: n0 = n2 + 1
性质4
具有 n 个结点的完全二叉树的高度为 k =(不大于log2 n的最大整数)+ 1
证明:
假设这 n 个结点组成的完全二叉树高度为 k
则: 2^(k - 1) < n <= 2^(k - 1)
因为 n 为整数,所以:
k - 1 <= log2 n< k
所以: k =(不大于log2 n的最大整数)+ 1
性质5
一棵具有 n 个结点的完全二叉树的高度为 k ,则按层次对结点进行编号(从上到下,从左到右)
对任意结点 i 有:
二叉树的存储结构设计
二叉树的继承结构:
设计要点:
BTree为二叉树结构,每个结点最多只有两个后继结点
BTreeNode只包含四个固定的公有成员(左孩子、右孩子、双亲结点、数据)
实现树形结构中的接口(增,删,查,等)
树是递归定义的,所以树中的函数也大都用递归实现!
BTreeNode的设计与实现:
继承自TreeNode(继承关系),添加两个结点指针(左孩子与右孩子)
BTree的设计与实现:
继承自Tree(继承关系),组合使用BTreeNode(组合关系)
BTree的实现架构图:
二叉树的结点查找操作
1、通过树中的元素的值查找
定义功能:find(node,value)
在node为根节点的树中查找value所在的结点
2、通过树中的结点的值查找
定义功能:find(node,obj)
在node为根节点的树中查找是否存在obj结点
二叉树中的插入操作
如何指定树中的结点插入在什么位置?
二叉树是非线性的,无法使用下标来定位数据元素
每一个结点都有唯一的前驱结点(父节点)
因此,必须找到(指明)前驱结点,才可以插入新结点
又:二叉树每一个结点都只有两个孩子结点
所以可以定义新的数据类型,指明插入的位置
// 添加一种新的数据类型,用来指明二叉树插入的位置
enum BTNodePos
{
ANY,
LEFT,
RIGHT
};
二叉树中的清除操作
定义清除操作功能:free(node)
清除node为根节点的树
释放树中的每一个结点(内存中的释放)
树中的结点可能来源与不同的存储空间,如何判断堆空间中的结点并释放?(PS:单凭内存地址很难判断是否为堆空间创建的)
使用工厂模式
在TreeNode中增加包含成员变量m_flag
将TreeNode中的operator new重载为包含成员函数(无法外部new出新对象)
提供工厂方法BTreeNode* NewNode()
在工厂方法中,new出新结点时,将m_flag设置为true
无参构造的时候,m_flag设置为false
只有这两种方式可以产生结点,所以可以通过m_flag判断是否为堆对象。
二叉树中的删除操作
删除操作成员函数的设计要点
将删除结点所代表的子树一并删除
如果删除中的结点所代表的子树中,有扔需要的数据怎么办?
删除后,返回为一棵独立的堆空间中的树
如果没有需要的数据呢?
返回为指向该子树的智能指针对象
不需要的话,因为生命周期原因,会直接析构
需要的话,使用智能指针对象指向即可继续使用
二叉树中的属性操作
1、二叉树中结点的数目
定义功能:count(node)
在node为根节点的二叉树中统计结点数目
2、二叉树的高度
定义功能:height(node)
获取node为根结点的二叉树的高度
3、二叉树的度数
定义功能:degree(node)
获取node为根结点的二叉树的度数
二叉树中的遍历方式
层次遍历
与Gtree的设计方式相同,设计思路:
使用游标的方式,利用LinkQueue实现
提供一组遍历相关函数:begin() current() next() end()
函数实现方式:
begin() → 将根节点压入队列
current() → 返回队头结点指向的数据元素
next() → 将队头结点弹出,将队头结点的孩子压入队列中
end() → 判断队列是否为空
递归遍历方式
1 先序遍历:
二叉树为空:
无操作,直接返回
二叉树不为空:
1 访问根结点中的数据元素
2 先序遍历左子树
3 先序遍历右子树
2 中序遍历:
二叉树为空:
无操作,直接返回
二叉树不为空:
1 中序遍历左子树
2 访问根结点中的数据元素
3 中序遍历右子树
3 后序遍历:
二叉树为空:
无操作,直接返回
二叉树不为空:
1 后序遍历左子树
2 后序遍历右子树
3 访问根结点中的数据元素
先序 中序 后序遍历函数
//先序遍历
void preOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
if(node)
{
queue.add(node);
preOrderTraversal(node->left,queue);
preOrderTraversal(node->right,queue);
}
}
//中序遍历
void inOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
if(node)
{
inOrderTraversal(node->left,queue);
queue.add(node);
inOrderTraversal(node->right,queue);
}
}
//后序遍历
void postOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
if(node)
{
postOrderTraversal(node->left,queue);
postOrderTraversal(node->right,queue);
queue.add(node);
}
}
遍历函数合并
因为层次遍历函数是一组函数(begin() current() next() end() ),需要一直移动游标,来获取下一层次的数据,而先序、中序、后序遍历的方式,一次就获得了遍历树的结果。为了让层次遍历与先序、中序、后序遍历兼容,封装出一个新的层次遍历函数和一个总的遍历函数(通过变量确定使用哪种遍历方式)。
新的层次遍历函数,这样也可以一次调用,queue中即是层次遍历的结果
void levelOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
if(node)
{
LinkQueue<BTreeNode<T>*> tmp;
tmp.add(root());
while(tmp.length() > 0)
{
BTreeNode<T>* n = tmp.front();
if(n->left != NULL)
{
tmp.add(n->left);
}
if(n->right != NULL)
{
tmp.add(n->right);
}
tmp.remove();
queue.add(n);
}
}
}
定义新数据类型,来选择遍历的方式
/*顺序遍历方式*/
enum BTTraversal
{
LevelOrder,//层次遍历
PreOrder,//先序遍历
InOrder,//中序遍历
PostOrder//后序遍历
};
总的遍历函数:因为二叉树是可以有编号的(通常从上到下,从左向右编号),所以返回值为数组类型,可以根据编号直接访问对应的数据元素,为了防止内存泄漏,采用了智能指针类型
void traversal(BTTraversal order,LinkQueue<BTreeNode<T>*>& queue)
{
switch(order)
{
case PreOrder:
preOrderTraversal(root(),queue);
break;
case InOrder:
inOrderTraversal(root(),queue);
break;
case PostOrder:
postOrderTraversal(root(),queue);
break;
case LevelOrder:
levelOrderTraversal(root(),queue);
break;
default:
THROW_EXCEPTION(InvalidParameterException,"Parameter order is invalid ...");
break;
}
}
SharedPointer<Array<T>> traversal(BTTraversal order)
{
DynamicArray<T>* ret = NULL;
LinkQueue<BTreeNode<T>*> queue;
traversal(order,queue);//根据选择的遍历方式进行遍历,遍历结果放入queue中
ret = new DynamicArray<T>(queue.length());
if(ret)
{
for(int i=0;i<ret->length();i++,queue.remove())
{
ret->set(i,queue.front()->value);
}
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create Array ...");
}
return ret;
}
二叉树的克隆操作
返回一棵堆空间上的新二叉树(与当前树相等)
定义功能:clone(node)
拷贝node为根结点的二叉树(数据对应位置相同)
二叉树的比较操作
对应位置的对应数据元素进行比较。容器里的数据类型需要支持比较操作。
定义功能:equal(node)
判断 lh 为根结点的二叉树与 rh 为根结点的二叉树是否相等
二叉树的相加操作
对应位置的对应数据元素相加,并返回一棵堆空间上的新二叉树。容器里的数据类型需要支持相加操作。
定义功能:add(node)
判断 lh 为根结点的二叉树与 rh 为根结点的二叉树相加
二叉树的线索化操作
将原本的树转换为双向链表的线索(原本的树没了)
根据二叉树的遍历次序进行线索化(结点有先后顺序)
利用左孩子结点指针(left)指向遍历中的前驱结点
利用右孩子结点指针(right)指向遍历中的后继结点
BTreeNode<T>* connect(LinkQueue<BTreeNode<T>*>& queue)
{
BTreeNode<T>* ret = NULL;
if(queue.length() > 0)
{
ret = queue.front();//初始首结点
BTreeNode<T>* slider = ret;
ret->left = NULL;//首结点无直接前驱
queue.remove();
while(queue.length() > 0)
{
slider->right = queue.front();//前后连接操作
queue.front()->left = slider;
slider = queue.front();//跳转下一个结点
queue.remove();
}
}
return ret;
}
//线索化操作,将原本的树转换为双向链表的线索(原本的树没了)
BTreeNode<T>* thread(BTTraversal order)
{
BTreeNode<T>* ret = NULL;
LinkQueue<BTreeNode<T>*> queue;
traversal(order,queue);//根据选择的遍历方式进行遍历,遍历结果放入queue中
ret = connect(queue);//将queue中的结点线索化为双向链表
this->m_root = NULL;//置为空树
m_queue.clear();
return ret;
}
BTree
BTree.h
#ifndef __BTree_H_
#define __BTree_H_
#include "include/GTree.h"
#include "include/BTreeNode.h"
#include "include/Exception.h"
#include "include/LinkQueue.h"
#include "include/Array.h"
#include "include/DynamicArray.h"
#include <iostream>
namespace JYlib
{
/*顺序遍历方式*/
enum BTTraversal
{
LevelOrder,//层次遍历
PreOrder,//先序遍历
InOrder,//中序遍历
PostOrder//后序遍历
};
/* 二叉树结构
* 二叉树类插入的对象的生命周期必须要比树的生命周期长
* 不然在调用或者析构时都会有问题(尽量不用局部变量)
* 层次遍历:begin next current end 调用时,需要
* 先begin,让队列里有元素,才可以使用current
*/
template < typename T >
class BTree : public Tree<T>
{
protected:
LinkQueue<BTreeNode<T>*> m_queue;//队列
virtual BTreeNode<T>* find(BTreeNode<T>* node,const T& value)const
{
BTreeNode<T>* ret = NULL;
if(node != NULL)
{
if(node->value == value)
{
ret = node;
}
else
{
if(ret == NULL)
{
ret = find(node->left,value);
}
if(ret == NULL)
{
ret = find(node->right,value);
}
}
}
return ret;
}
virtual BTreeNode<T>* find(BTreeNode<T>* node,BTreeNode<T>* obj)const
{
BTreeNode<T>* ret = NULL;
if(node != NULL)
{
if(node == obj)
{
ret = node;
}
else
{
if(ret == NULL)
{
ret = find(node->left,obj);
}
if(ret == NULL)
{
ret = find(node->right,obj);
}
}
}
return ret;
}
virtual bool insert(BTreeNode<T>* node,BTreeNode<T>* n_parent,BTNodePos pos)
{
bool ret = true;
if(ANY == pos)
{
if(n_parent->left == NULL)
{
n_parent->left = node;
}
else if(n_parent->right == NULL)
{
n_parent->right = node;
}
else
{
ret = false;
}
}
else if(LEFT == pos)
{
if(n_parent->left == NULL)
{
n_parent->left = node;
}
else
{
ret = false;
}
}
else if(RIGHT == pos)
{
if(n_parent->right == NULL)
{
n_parent->right = node;
}
else
{
ret = false;
}
}
else
{
ret = false;
}
return ret;
}
virtual void remove(BTreeNode<T>* node,BTree<T>*& ret)
{
ret = new BTree<T>();
if(ret)
{
if(root() == node)
{
this->m_root = NULL;
}
else
{
BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);
if(parent->left == node)
{
parent->left = NULL;
}
else if(parent->right == node)
{
parent->right = NULL;
}
node->parent = NULL;
}
ret->m_root = node;//作为新的一棵树返回
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new tree ...");
}
}
virtual void free(BTreeNode<T>* node)
{
if(node)
{
free(node->left);
free(node->right);
if(node->flag() == true)
{
//std::cout << "delete " << node->value << std::endl;
delete node;
}
}
}
int count(BTreeNode<T>* node)const
{
//左子树与右子树的子结点数量和,再加上当前的(1)
return (node != NULL) ? (count(node->left) + count(node->right)+1) : 0;
}
int height(BTreeNode<T>* node)const
{
int ret = 0;
if(node)
{
int l = height(node->left);
int r = height(node->right);
//左子树与右子树高度取最大高度,再加上当前的(1)
ret = (l>r ? l : r) + 1;
}
return ret;
}
int degree(BTreeNode<T>* node)const
{
int ret = 0;
if(node)
{
BTreeNode<T>* child[] = {node->left,node->right};
ret = !!node->left + !!node->right;
for(int i=0;(i<2)&&(ret<2);i++)
{
int d = degree(child[i]);
if(ret < d)
{
ret = d;
}
}
}
return ret;
}
//先序遍历
void preOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
if(node)
{
queue.add(node);
preOrderTraversal(node->left,queue);
preOrderTraversal(node->right,queue);
}
}
//中序遍历
void inOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
if(node)
{
inOrderTraversal(node->left,queue);
queue.add(node);
inOrderTraversal(node->right,queue);
}
}
//后序遍历
void postOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
if(node)
{
postOrderTraversal(node->left,queue);
postOrderTraversal(node->right,queue);
queue.add(node);
}
}
//层次遍历
void levelOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
if(node)
{
LinkQueue<BTreeNode<T>*> tmp;
tmp.add(root());
while(tmp.length() > 0)
{
BTreeNode<T>* n = tmp.front();
if(n->left != NULL)
{
tmp.add(n->left);
}
if(n->right != NULL)
{
tmp.add(n->right);
}
tmp.remove();
queue.add(n);
}
}
}
BTreeNode<T>* clone(BTreeNode<T>* node)const
{
BTreeNode<T>* ret = NULL;
if(node)
{
ret = BTreeNode<T>::NewNode();
if(ret)
{
ret->value = node->value;
ret->left = clone(node->left);
ret->right = clone(node->right);
if(ret->left != NULL)
{
ret->left->parent = ret;
}
if(ret->right != NULL)
{
ret->right->parent = ret;
}
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new node ...");
}
}
return ret;
}
bool equal(BTreeNode<T>* lt,BTreeNode<T>* rt)
{
if(lt == rt)
{
return true;
}
else if((lt != NULL)&&(rt != NULL))
{
return (lt->value == rt->value) && equal(lt->left,rt->left) && equal(lt->right,rt->right);
}
else
{
return false;
}
}
BTreeNode<T>* add(BTreeNode<T>* lt,BTreeNode<T>* rt)
{
BTreeNode<T>* ret = NULL;
if((lt != NULL)&&(rt != NULL))
{
ret = BTreeNode<T>::NewNode();
if(ret)
{
ret->value = lt->value + rt->value;
ret->left = add(lt->left,rt->left);
ret->right = add(lt->right,rt->right);
if(ret->left != NULL)
{
ret->left->parent = ret;
}
if(ret->right != NULL)
{
ret->right->parent = ret;
}
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new node ...");
}
}
else if((lt == NULL)&&(rt != NULL))
{
ret = clone(rt);
}
else if((lt != NULL)&&(rt == NULL))
{
ret = clone(lt);
}
return ret;
}
void traversal(BTTraversal order,LinkQueue<BTreeNode<T>*>& queue)
{
switch(order)
{
case PreOrder:
preOrderTraversal(root(),queue);
break;
case InOrder:
inOrderTraversal(root(),queue);
break;
case PostOrder:
postOrderTraversal(root(),queue);
break;
case LevelOrder:
levelOrderTraversal(root(),queue);
break;
default:
THROW_EXCEPTION(InvalidParameterException,"Parameter order is invalid ...");
break;
}
}
BTreeNode<T>* connect(LinkQueue<BTreeNode<T>*>& queue)
{
BTreeNode<T>* ret = NULL;
if(queue.length() > 0)
{
ret = queue.front();
BTreeNode<T>* slider = ret;
ret->left = NULL;
queue.remove();
while(queue.length() > 0)
{
slider->right = queue.front();//前后连接操作
queue.front()->left = slider;
slider = queue.front();//跳转下一个结点
queue.remove();
}
}
return ret;
}
public:
bool insert(TreeNode<T>* node,BTNodePos pos)
{
bool ret = true;
if(node != NULL)
{
if(this->m_root == NULL)
{
this->m_root = node;
node->parent = NULL;
}
else
{
BTreeNode<T>* n_parent = find(node->parent);
if(n_parent != NULL)
{
insert(dynamic_cast<BTreeNode<T>*>(node),n_parent,pos);
}
else
{
THROW_EXCEPTION(InvalidParameterException,"Invalid parent tree node ...");
}
}
}
else
{
THROW_EXCEPTION(InvalidParameterException,"Parameter node can not be NULL ...");
}
return ret;
}
bool insert(TreeNode<T>* node)
{
return insert(node,ANY);
}
bool insert(const T& value,TreeNode<T>* parent,BTNodePos pos)
{
bool ret = true;
BTreeNode<T>* new_node = BTreeNode<T>::NewNode();
if(new_node != NULL)
{
new_node->value = value;
new_node->parent = parent;
ret = insert(new_node,pos);
if(ret == false)//插入失败时,删除新节点,防止内存泄漏
{
delete new_node;
}
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new_node ...");
}
return ret;
}
bool insert(const T& value,TreeNode<T>* parent)
{
return insert(value,parent,ANY);
}
//返回智能指针类型,函数返回值生命周期只有一条语句,如果没有智能指针接手,就会析构
SharedPointer< Tree<T> > remove(const T& value)
{
BTree<T>* ret = NULL;
BTreeNode<T>* del_node = find(value);
if(del_node != NULL)
{
remove(del_node,ret);
m_queue.clear();
}
else
{
THROW_EXCEPTION(InvalidParameterException,"Can not find the node via parameter value ...");
}
return ret;
}
SharedPointer< Tree<T> > remove(TreeNode<T>* node)
{
BTree<T>* ret = NULL;
BTreeNode<T>* del_node = find(node);
if(del_node != NULL)
{
remove(del_node,ret);
m_queue.clear();
}
else
{
THROW_EXCEPTION(InvalidParameterException,"Parameter node is invalid ...");
}
return ret;
}
BTreeNode<T>* find(const T& value)const
{
return find(root(),value);
}
BTreeNode<T>* find(TreeNode<T>* node)const
{
return find(root(),dynamic_cast<BTreeNode<T>*>(node));
}
BTreeNode<T>* root()const
{
return dynamic_cast<BTreeNode<T>*>(this->m_root);
}
int degree()const
{
return degree(root());
}
int count()const
{
return count(root());
}
int height()const
{
return height(root());
}
bool begin()
{
bool ret = (root() != NULL);
if(ret)
{
m_queue.clear();
m_queue.add(root());
}
return ret;
}
bool next()
{
bool ret = m_queue.length() > 0;
if(ret)
{
if(m_queue.front()->left != NULL)
{
m_queue.add(m_queue.front()->left);
}
if(m_queue.front()->right != NULL)
{
m_queue.add(m_queue.front()->right);
}
m_queue.remove();
}
return ret;
}
T current()
{
if(!end())
{
return m_queue.front()->value;
}
else
{
THROW_EXCEPTION(InvalidOperationException,"No value at current queue ...");
}
}
bool end()
{
return (m_queue.length() == 0);
}
//顺序遍历访问方式(先序、中序、后序、层次)
SharedPointer<Array<T>> traversal(BTTraversal order)
{
DynamicArray<T>* ret = NULL;
LinkQueue<BTreeNode<T>*> queue;
traversal(order,queue);//根据order选择遍历方式
ret = new DynamicArray<T>(queue.length());
if(ret)
{
for(int i=0;i<ret->length();i++,queue.remove())
{
ret->set(i,queue.front()->value);
}
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create Array ...");
}
return ret;
}
//线索化操作,将原本的树转换为双向链表的线索(原本的树没了)
BTreeNode<T>* thread(BTTraversal order)
{
BTreeNode<T>* ret = NULL;
LinkQueue<BTreeNode<T>*> queue;
traversal(order,queue);
ret = connect(queue);
this->m_root = NULL;//置为空树
m_queue.clear();
return ret;
}
//二叉树克隆
SharedPointer<BTree<T>> clone()const
{
BTree<T>* ret = new BTree();
if(ret)
{
ret->m_root = clone(root());
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new tree ...");
}
return ret;
}
//二叉树相加
SharedPointer<BTree<T>> add(const BTree<T>& btree)
{
BTree<T>* ret = new BTree<T>();
if(ret)
{
ret->m_root = add(root(),btree.root());
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new tree ...");
}
return ret;
}
bool operator ==(const BTree<T>& btree)
{
return equal(root(),btree.root());
}
bool operator !=(const BTree<T>& btree)
{
return !(*this == btree);
}
void clear()
{
free(root());
m_queue.clear();
}
~BTree()
{
clear();
}
};
}
#endif
BTreeNode
BTreeNode.h
#ifndef __BTreeNode_H_
#define __BTreeNode_H_
#include "include/TreeNode.h"
namespace JYlib
{
/* 关于析构
* 局部变量的生命周期只在局部有用,如果使用局部变量
* 做了首结点,并且没有主动调用析构函数。等Tree的生命
* 周期结束时,自动调用析构函数时,局部变量(头结点)生命
* 已经结束,m_root的地址将为NULL,析构无法执行.
* 不要使用局部变量作为头结点!
* 如果非要使用,在确保头结点的生命周期结束前,调用
* 树的析构函数.
*/
// 添加一种新的数据类型,用来指明二叉树插入的位置
enum BTNodePos
{
ANY,
LEFT,
RIGHT
};
/*
二叉树结点
孩子兄弟表示法:每个结点都有一个指向孩子一个指向兄弟的指针
通过这种表示法,可以描述任何的树形结构
二叉树由其抽象而来,抽象出每个结点都只有两个孩子,左孩子与右孩子
*/
template < typename T >
class BTreeNode : public TreeNode<T>
{
public:
BTreeNode<T>* left;
BTreeNode<T>* right;
BTreeNode()
{
left = NULL;
right = NULL;
}
static BTreeNode<T>* NewNode()
{
BTreeNode<T>* ret = new BTreeNode<T>();
if(ret)
{
ret->m_flag = true;
}
return ret;
}
};
}
#endif