//对二叉树状态性质的判断
//以内联函数的形式给出
template<typename T>inline int stature(T* cur) {/*当前节点的高度*/
//cur ? cur->height : -1;
if (cur) return cur->height;
else return -1;
}
template<typename T>inline bool IsRoot(T* cur) {/*是否是根节点*/
return !cur->parent;
}
template<typename T>inline bool IsLChild(T* cur) {/*是否是左孩子*/
return !IsRoot(cur) && (cur == cur->parent->left);
}
template<typename T>inline bool IsRChild(T* cur) {/*是否是右孩子*/
return !IsRoot(cur) && (cur == cur->parent->right);
}
/*是否是父节点*/
template<typename T>inline bool HasParent(T* cur) { return !IsRoot(cur); }
/*是否具有左孩子*/
template<typename T>inline bool HasLChild(T* cur) {
//cur->left ? true : false;
if (cur->left) return true;
else return false;
}
/*是否具有右孩子*/
template<typename T>inline bool HasRChild(T* cur) {
if (cur->right)
return true;
else
return false;
}
/*是否具有孩子*/
template<typename T>inline bool HasChild(T* cur) { HasLChild(cur) || HasRChild(cur); }
/*是否同时具有左孩子和右孩子*/
template<typename T>inline bool HasBothChild(T* cur) { HasLChild(cur) && HasRChild(cur); }
/*是否是叶节点*/
template<typename T>inline bool IsLeaf(T* cur) { !HasChild(cur); }
//与BinNode具有特定关系的节点及指针
template<typename T>inline T* FromParentTo(T* cur) {/*来自父亲的引用*/
//IsRoot(cur) ? _root : (IsLChild(cur) ? cur->parent->left : cur->parent->right);
if (IsRoot(cur)) {
return cur;
}
else if (IsLChild(cur)) {
return cur->parent->left;
}
else {
return cur->parent->right;
}
}
二叉树的表示方法
一、引理:多叉树
一般地,树中各节点的孩子数目并不确定。每个节点的孩子均不超过K个有根树,称作K叉树。
多叉树有三种表示方法:
- 父亲法
- 孩子法
- 父亲+孩子法
1、父亲法即底层组织为向量结构,记录每个节点的父亲。根据向量结构的优势可在O(1)时间得到当前节点的父子关系,但是孩子节点的查找需要遍历完所有节点,不得不花费O(n)时间。
2、孩子法可以令底层结构组织为向量或是列表,注重孩子节点的查找,父节点的查找花费O(n)时间
3、父亲+孩子法即综合二者优势,底层组织为边表结构,既记录父节点同时高效维护一个子序列来记录孩子节点。
如若建立某种关系使得能够由多叉树到二叉树的转换,并使得在此转换的意义下,任一多叉树都等价于一颗二叉树。
二、长子+兄弟法
有序多叉树中任一非叶节点都有唯一的“长子”,而且从该“长子”出发,可按照预先约定或指定的次序遍历所有孩子节点。因此,任意一颗有序多叉树都可转换为二叉树。
所以二叉树可以用二叉链表来描述,
struct BinNode{
BinNode* left;
BinNode* right;
int val;
}
而三叉链表,加上父节点的指针,以“长子+兄弟+父亲”法描述一颗二叉树,比二叉链表更清晰。
//BinNode模板类
#ifndef __BINNODE_H__
#define __BINNODE_H__
#define BNodePosi(T) BinNode<T>*
//二叉树颜色,以便后续实现红黑树
const enum RBCOLOR{
RB_RED = 1,
RB_BLACK
};
template<typename T> class BinNode{
public:
//数据成员,可以进一步封装,这里全部以公有给出,方便测试。
BNodePosi(T) parent; BNodePosi(T) left; BNodePosi(T) right;
int height;
int npl;//左式堆
RBCOLOR color;
T data;
BinNode() :parent(NULL), left(NULL), right(NULL), height(0), npl(1), color(RB_RED) {}
BinNode(T e, BNodePosi(T) p = NULL, BNodePosi(T) left = NULL, BNodePosi(T) right = NULL, int h = 0, int l = 1, RBCOLOR C = RB_RED) :
data(e), parent(p), left(left), right(right), height(h), npl(l), color(C) {}
BinNode(BinNode<T>& node) {
parent = node->parent; left = node->left; right = node->right;
height = node->height; npl = node->npl; color = node->color;
data = node->data;
}
int size();
BNodePosi(T) insertAsLC(T const&);
BNodePosi(T) insertAsRC(T const&);
BNodePosi(T) succ();
BNodePosi(T) prec();
/*
*遍历接口是以函数对象的形式实现,也可以函数指针方式遍历。
*template<typnename T>void BinNode<T>::travLevel(void(* visit)(T&)){}
*/
template<typename VST>void travLevel(VST& visit);
template<typename VST>void travPre(VST& visit);
template<typename VST>void travIn(VST& visit);
template<typename VST>void travPost(VST& visit);
bool operator<(BinNode const& bi) { return this->data < bi.data; }
bool operator==(BinNode const& bi) { return this->data == bi.data; }
bool operator>(BinNode const& bi) { return this->data > bi.data; }
}