※数据结构※→☆非线性结构(tree)☆============二叉树 顺序存储结构(tree binary sequence)(十九)
二叉树
在计算机科学中,二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用作二叉查找树和二叉堆或是二叉排序树。二叉树的每个结点至多只有二棵子树(不存在出度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2的 i -1次方个结点;深度为k的二叉树至多有2^(k) -1个结点;对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为,出度为2的结点数为,则=+ 1。
基本形态
二叉树也是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:
(1)空二叉树——(a);
(2)只有一个根结点的二叉树——(b);
(3)只有左子树——(c);
(4)只有右子树——(d);
(5)完全二叉树——(e)
注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。
重要概念
(1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
(2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
(3)深度——二叉树的层数,就是高度。
性质
(1) 在二叉树中,第i层的结点总数不超过2^(i-1);
(2) 深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点;
(3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
(4) 具有n个结点的完全二叉树的深度为int(log2n)+1
(5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
若I为结点编号则 如果I>1,则其父结点的编号为I/2;
如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;
如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。
(6)给定N个节点,能构成h(N)种不同的二叉树。
h(N)为卡特兰数的第N项。h(n)=C(n,2*n)/(n+1)。
(7)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i
1.完全二叉树 (Complete Binary Tree)
若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层从右向左连续缺若干结点,这就是完全二叉树。
2.满二叉树 (Full Binary Tree)
一个高度为h的二叉树包含正是2^h-1元素称为满二叉树。
二叉树四种遍历
1.先序遍历 (仅二叉树)
指先访问根,然后访问孩子的遍历方式
非递归实现
利用栈实现,先取根节点,处理节点,然后依次遍历左节点,遇到有右节点压入栈,向左走到尽头。然后从栈中取出右节点,处理右子树。
/*** PreOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note Pre-order traversal
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::PreOrderTraversal(AL_ListSeq<T>& listOrder) const
{
if (NULL == m_pRootNode) {
return FALSE;
} listOrder.Clear(); //Recursion Traversal
PreOrderTraversal(m_pRootNode, listOrder);
return TRUE; //Not Recursion Traversal
AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStack;
AL_TreeNodeBinSeq<T>* pTreeNode = m_pRootNode; while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {
while (NULL != pTreeNode) {
listOrder.InsertEnd(pTreeNode->GetData());
if (NULL != pTreeNode->GetChildRight()) {
//push the child right to stack
cStack.Push(pTreeNode->GetChildRight());
}
pTreeNode = pTreeNode->GetChildLeft();
} if (TRUE == cStack.Pop(pTreeNode)) {
if (NULL == pTreeNode) {
return FALSE;
}
}
else {
return FALSE;
} }
return TRUE;
}
递归实现
/**
* PreOrderTraversal
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param AL_ListSeq<T>& listOrder <OUT>
* @return VOID
* @note Pre-order traversal
* @attention Recursion Traversal
*/
template<typename T> VOID
AL_TreeBinSeq<T>::PreOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const
{
if (NULL == pCurTreeNode) {
return;
}
//Do Something with root
listOrder.InsertEnd(pCurTreeNode->GetData()); if(NULL != pCurTreeNode->GetChildLeft()) {
PreOrderTraversal(pCurTreeNode->GetChildLeft(), listOrder);
} if(NULL != pCurTreeNode->GetChildRight()) {
PreOrderTraversal(pCurTreeNode->GetChildRight(), listOrder);
}
}
2.中序遍历(仅二叉树)
指先访问左(右)孩子,然后访问根,最后访问右(左)孩子的遍历方式
非递归实现
利用栈实现,先取根节点,然后依次遍历左节点,将左节点压入栈,向左走到尽头。然后从栈中取出左节点,处理节点。然后处理其右子树。
/**
* InOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note In-order traversal
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::InOrderTraversal(AL_ListSeq<T>& listOrder) const
{
if (NULL == m_pRootNode) {
return FALSE;
} listOrder.Clear(); //Recursion Traversal
InOrderTraversal(m_pRootNode, listOrder);
return TRUE; //Not Recursion Traversal
AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStack;
AL_TreeNodeBinSeq<T>* pTreeNode = m_pRootNode; while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {
while (NULL != pTreeNode) {
cStack.Push(pTreeNode);
pTreeNode = pTreeNode->GetChildLeft();
} if (TRUE == cStack.Pop(pTreeNode)) {
if (NULL != pTreeNode) {
listOrder.InsertEnd(pTreeNode->GetData());
if (NULL != pTreeNode->GetChildRight()){
//child right exist, push the node, and loop it's left child to push
pTreeNode = pTreeNode->GetChildRight();
}
else {
//to pop the node in the stack
pTreeNode = NULL;
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
} return TRUE;
}
递归实现
/**
* InOrderTraversal
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param AL_ListSeq<T>& listOrder <OUT>
* @return VOID
* @note In-order traversal
* @attention Recursion Traversal
*/
template<typename T> VOID
AL_TreeBinSeq<T>::InOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const
{
if (NULL == pCurTreeNode) {
return;
} if(NULL != pCurTreeNode->GetChildLeft()) {
InOrderTraversal(pCurTreeNode->GetChildLeft(), listOrder);
} //Do Something with root
listOrder.InsertEnd(pCurTreeNode->GetData()); if(NULL != pCurTreeNode->GetChildRight()) {
InOrderTraversal(pCurTreeNode->GetChildRight(), listOrder);
}
}
3.后序遍历(仅二叉树)
指先访问孩子,然后访问根的遍历方式
非递归实现
利用栈实现,先取根节点,然后依次遍历左节点,将左节点压入栈,向左走到尽头。然后从栈中取出左节点,处理节点。处理其右节点,还需要记录已经使用过的节点,比较麻烦和复杂。大致思路如下:
- 1.找到最左边的子节点
- 2.如果最左边的子节点有右节点,处理右节点(类似1)
- 3.从栈里弹出节点处理
- 3.当碰到左右节点都存在的节点时,需要进行记录了回归节点了。然后以当前节点的右子树进行处理
- 4.碰到回归节点时,把当前的最后一个元素消除(因为后面还会回归到这个点的)。
/**
* PostOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note Post-order traversal
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::PostOrderTraversal(AL_ListSeq<T>& listOrder) const
{
if (NULL == m_pRootNode) {
return FALSE;
} listOrder.Clear(); //Recursion Traversal
PostOrderTraversal(m_pRootNode, listOrder);
return TRUE; //Not Recursion Traversal
AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStack;
AL_TreeNodeBinSeq<T>* pTreeNode = m_pRootNode;
AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStackReturn;
AL_TreeNodeBinSeq<T>* pTreeNodeReturn = NULL; while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {
while (NULL != pTreeNode) {
cStack.Push(pTreeNode);
if (NULL != pTreeNode->GetChildLeft()) {
pTreeNode = pTreeNode->GetChildLeft();
}
else {
//has not left child, get the right child
pTreeNode = pTreeNode->GetChildRight();
}
} if (TRUE == cStack.Pop(pTreeNode)) {
if (NULL != pTreeNode) {
listOrder.InsertEnd(pTreeNode->GetData());
if (NULL != pTreeNode->GetChildLeft() && NULL != pTreeNode->GetChildRight()){
//child right exist
cStackReturn.Top(pTreeNodeReturn);
if (pTreeNodeReturn != pTreeNode) {
listOrder.RemoveAt(listOrder.Length()-1);
cStack.Push(pTreeNode);
cStackReturn.Push(pTreeNode);
pTreeNode = pTreeNode->GetChildRight();
}
else {
//to pop the node in the stack
cStackReturn.Pop(pTreeNodeReturn);
pTreeNode = NULL;
}
}
else {
//to pop the node in the stack
pTreeNode = NULL;
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
} return TRUE;
}
递归实现
/**
* PostOrderTraversal
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param AL_ListSeq<T>& listOrder <OUT>
* @return VOID
* @note Post-order traversal
* @attention Recursion Traversal
*/
template<typename T> VOID
AL_TreeBinSeq<T>::PostOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const
{
if (NULL == pCurTreeNode) {
return;
} if(NULL != pCurTreeNode->GetChildLeft()) {
PostOrderTraversal(pCurTreeNode->GetChildLeft(), listOrder);
} if(NULL != pCurTreeNode->GetChildRight()) {
PostOrderTraversal(pCurTreeNode->GetChildRight(), listOrder);
} //Do Something with root
listOrder.InsertEnd(pCurTreeNode->GetData());
}
4.层次遍历
一层一层的访问,所以一般用广度优先遍历。
非递归实现
利用链表或者队列均可实现,先取根节点压入链表或者队列,依次从左往右体访问子节点,压入链表或者队列。直至处理完所有节点。
/**
* LevelOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note Level-order traversal
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::LevelOrderTraversal(AL_ListSeq<T>& listOrder) const
{
if (TRUE == IsEmpty()) {
return FALSE;
} if (NULL == m_pRootNode) {
return FALSE;
}
listOrder.Clear();
/*
AL_ListSeq<AL_TreeNodeBinSeq<T>*> listNodeOrder;
listNodeOrder.InsertEnd(m_pRootNode);
//loop the all node
DWORD dwNodeOrderLoop = 0x00;
AL_TreeNodeBinSeq<T>* pNodeOrderLoop = NULL;
AL_TreeNodeBinSeq<T>* pNodeOrderChild = NULL;
while (TRUE == listNodeOrder.Get(pNodeOrderLoop, dwNodeOrderLoop)) {
dwNodeOrderLoop++;
if (NULL != pNodeOrderLoop) {
listOrder.InsertEnd(pNodeOrderLoop->GetData());
pNodeOrderChild = pNodeOrderLoop->GetChildLeft();
if (NULL != pNodeOrderChild) {
queueOrder.Push(pNodeOrderChild);
}
pNodeOrderChild = pNodeOrderLoop->GetChildRight();
if (NULL != pNodeOrderChild) {
queueOrder.Push(pNodeOrderChild);
}
}
else {
//error
return FALSE;
}
}
return TRUE;
*/ AL_QueueSeq<AL_TreeNodeBinSeq<T>*> queueOrder;
queueOrder.Push(m_pRootNode); AL_TreeNodeBinSeq<T>* pNodeOrderLoop = NULL;
AL_TreeNodeBinSeq<T>* pNodeOrderChild = NULL;
while (FALSE == queueOrder.IsEmpty()) {
if (TRUE == queueOrder.Pop(pNodeOrderLoop)) {
if (NULL != pNodeOrderLoop) {
listOrder.InsertEnd(pNodeOrderLoop->GetData());
pNodeOrderChild = pNodeOrderLoop->GetChildLeft();
if (NULL != pNodeOrderChild) {
queueOrder.Push(pNodeOrderChild);
}
pNodeOrderChild = pNodeOrderLoop->GetChildRight();
if (NULL != pNodeOrderChild) {
queueOrder.Push(pNodeOrderChild);
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
}
return TRUE;
}
递归实现 (无)
======================================================================================================
树(tree)是包含n(n>0)个结点的有穷集合,其中:
- 每个元素称为结点(node);
- 有一个特定的结点被称为根结点或树根(root)。
- 除根结点之外的其余数据元素被分为m(m≥0)个互不相交的集合T1,T2,……Tm-1,其中每一个集合Ti(1<=i<=m)本身也是一棵树,被称作原树的子树(subtree)。
树也可以这样定义:树是由根结点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的结点,所定义的关系称为父子关系。父子关系在树的结点之间建立了一个层次结构。在这种层次结构中有一个结点具有特殊的地位,这个结点称为该树的根结点,或称为树根。
我们可以形式地给出树的递归定义如下:
- 单个结点是一棵树,树根就是该结点本身。
- 设T1,T2,..,Tk是树,它们的根结点分别为n1,n2,..,nk。用一个新结点n作为n1,n2,..,nk的父亲,则得到一棵新树,结点n就是新树的根。我们称n1,n2,..,nk为一组兄弟结点,它们都是结点n的子结点。我们还称n1,n2,..,nk为结点n的子树。
- 空集合也是树,称为空树。空树中没有结点。
树的四种遍历
1.先序遍历 (仅二叉树)
指先访问根,然后访问孩子的遍历方式
2.中序遍历(仅二叉树)
指先访问左(右)孩子,然后访问根,最后访问右(左)孩子的遍历方式
3.后序遍历(仅二叉树)
指先访问孩子,然后访问根的遍历方式
4.层次遍历
一层一层的访问,所以一般用广度优先遍历。
======================================================================================================
树结点 顺序存储结构(tree node sequence)
结点:
包括一个数据元素及若干个指向其它子树的分支;例如,A,B,C,D等。
在数据结构的图形表示中,对于数据集合中的每一个数据元素用中间标有元素值的方框表示,一般称之为数据结点,简称结点。
在C语言中,链表中每一个元素称为“结点”,每个结点都应包括两个部分:一为用户需要用的实际数据;二为下一个结点的地址,即指针域和数据域。
数据结构中的每一个数据结点对应于一个储存单元,这种储存单元称为储存结点,也可简称结点
树结点(树节点):
树节点相关术语:
- 节点的度:一个节点含有的子树的个数称为该节点的度;
- 叶节点或终端节点:度为0的节点称为叶节点;
- 非终端节点或分支节点:度不为0的节点;
- 双亲节点或父节点:若一个结点含有子节点,则这个节点称为其子节点的父节点;
- 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
- 兄弟节点:具有相同父节点的节点互称为兄弟节点;
- 节点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
- 堂兄弟节点:双亲在同一层的节点互为堂兄弟;
- 节点的祖先:从根到该节点所经分支上的所有节点;
- 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
根据树结点的相关定义,采用“双亲孩子表示法”。其属性如下:
DWORD m_dwLevel; //Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;
T m_data; //the friend class can use it directly AL_TreeNodeSeq<T>* m_pParent; //Parent position
AL_ListSeq<AL_TreeNodeSeq<T>*> m_listChild; //All Child tree node
树的几种表示法
在实际中,可使用多种形式的存储结构来表示树,既可以采用顺序存储结构,也可以采用链式存储结构,但无论采用何种存储方式,都要求存储结构不但能存储各结点本身的数据信息,还要能唯一地反映树中各结点之间的逻辑关系。
1.双亲表示法
由于树中的每个结点都有唯一的一个双亲结点,所以可用一组连续的存储空间(一维数组)存储树中的各个结点,数组中的一个元素表示树中的一个结点,每个结点含两个域,数据域存放结点本身信息,双亲域指示本结点的双亲结点在数组中位置。
2.孩子表示法
1.多重链表:每个结点有多个指针域,分别指向其子树的根
1)结点同构:结点的指针个数相等,为树的度k,这样n个结点度为k的树必有n(k-1)+1个空链域.
2)结点不同构:结点指针个数不等,为该结点的度d
2.孩子链表:每个结点的孩子结点用单链表存储,再用含n个元素的结构数组指向每个孩子链表
3.双亲孩子表示法
1.双亲表示法,PARENT(T,x)可以在常量时间内完成,但是求结点的孩子时需要遍历整个结构。
2.孩子链表表示法,适于那些涉及孩子的操作,却不适于PARENT(T,x)操作。
3.将双亲表示法和孩子链表表示法合在一起,可以发挥以上两种存储结构的优势,称为带双亲的孩子链表表示法
4.双亲孩子兄弟表示法 (二叉树专用)
又称为二叉树表示法,以二叉链表作为树的存储结构。
顺序存储结构
在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构.
顺序存储结构是存储结构类型中的一种,该结构是把逻辑上相邻的节点存储在物理位置上相邻的存储单元中,结点之间的逻辑关系由存储单元的邻接关系来体现。由此得到的存储结构为顺序存储结构,通常顺序存储结构是借助于计算机程序设计语言(例如c/c++)的数组来描述的。
顺序存储结构的主要优点是节省存储空间,因为分配给数据的存储单元全用存放结点的数据(不考虑c/c++语言中数组需指定大小的情况),结点之间的逻辑关系没有占用额外的存储空间。采用这种方法时,可实现对结点的随机存取,即每一个结点对应一个序号,由该序号可以直接计算出来结点的存储地址。但顺序存储方法的主要缺点是不便于修改,对结点的插入、删除运算时,可能要移动一系列的结点。
优点:
随机存取表中元素。缺点:插入和删除操作需要移动元素。
本代码默认list可以容纳的item数目为100个,用户可以自行设置item数目。当list饱和时,由于Tree是非线性结构,动态扩展内存相当麻烦。因此示例中的Demo及代码将不会动态扩展内存。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以后的笔记潇汀会尽量详细讲解一些相关知识的,希望大家继续关注我的博客。
本节笔记到这里就结束了。
潇汀一有时间就会把自己的学习心得,觉得比较好的知识点写出来和大家一起分享。
编程开发的路很长很长,非常希望能和大家一起交流,共同学习,共同进步。
如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨编程相关的问题。
最后,谢谢你们一直的支持~~~
C++完整个代码示例(代码在VS2005下测试可运行)
AL_TreeNodeBinSeq.h
/**
@(#)$Id: AL_TreeNodeBinSeq.h 56 2013-09-24 08:47:13Z xiaoting $
@brief Each of the data structure corresponds to a data node storage unit, this storage unit is called storage node, the node can
also be referred to. The related concepts of tree node
1.degree degree node: A node of the subtree containing the number is called the node degree;
2.leaf leaf nodes or terminal nodes: degree 0 are called leaf nodes;
3.branch non-terminal node or branch node: node degree is not 0;
4.parent parent node or the parent node: If a node contains a child node, this node is called its child node's parent;
5.child child node or child node: A node subtree containing the root node is called the node's children;
6.slibing sibling nodes: nodes with the same parent node is called mutual sibling;
7.ancestor ancestor node: from the root to the node through all the nodes on the branch;
8.descendant descendant nodes: a node in the subtree rooted at any node is called the node's descendants. ////////////////////////////////Binary Tree//////////////////////////////////////////
In computer science, a binary tree is that each node has at most two sub-trees ordered tree. Usually the root of the subtree is
called "left subtree" (left subtree) and the "right subtree" (right subtree). Binary tree is often used as a binary search tree
and binary heap or a binary sort tree. Binary tree each node has at most two sub-tree (does not exist a degree greater than two
nodes), left and right sub-tree binary tree of the points, the order can not be reversed. Binary i-th layer of at most 2 power
nodes i -1; binary tree of depth k at most 2 ^ (k) -1 nodes; for any binary tree T, if it is the terminal nodes (i.e. leaf nodes)
is, the nodes of degree 2 is, then = + 1. ////////////////////////////////Sequential storage structure//////////////////////////////////////////
Using a set of addresses in the computer storage unit sequentially stores continuous linear form of individual data elements, called
the linear order of the table storage structure. Sequential storage structure is a type of a storage structure, the structure is the logically adjacent nodes stored in the physical
location of the adjacent memory cells, the logical relationship between nodes from the storage unit to reflect the adjacency.
Storage structure thus obtained is stored in order structure, usually by means of sequential storage structure computer programming
language (e.g., c / c) of the array to describe. The main advantage of the storage structure in order to save storage space, because the allocation to the data storage unit storing
all nodes with data (without regard to c / c language in the array size required for the case), the logical relationship between
the nodes does not take additional storage space. In this method, the node can be realized on a random access, that is, each node
corresponds to a number, the number can be calculated directly from the node out of the memory address. However, the main
disadvantage of sequential storage method is easy to modify the node insert, delete operations, may have to move a series of nodes.
Benefits:
Random Access table elements.
Disadvantages:
insert and delete operations need to move elements. @Author $Author: xiaoting $
@Date $Date: 2013-09-24 16:47:13 +0800 (周二, 24 九月 2013) $
@Revision $Revision: 56 $
@URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeBinSeq.h $
@Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeBinSeq.h 56 2013-09-24 08:47:13Z xiaoting $
*/ #ifndef CXX_AL_TREENODEBINSEQ_H
#define CXX_AL_TREENODEBINSEQ_H #ifndef CXX_AL_LISTSEQ_H
#include "AL_ListSeq.h"
#endif #ifndef CXX_AL_QUEUESEQ_H
#include "AL_QueueSeq.h"
#endif ///////////////////////////////////////////////////////////////////////////
// AL_TreeNodeBinSeq
/////////////////////////////////////////////////////////////////////////// template<typename T> class AL_TreeBinSeq; template<typename T>
class AL_TreeNodeBinSeq
{
public:
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
~AL_TreeNodeBinSeq(); /**
* GetLevel
*
* @param
* @return DWORD
* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;
* @attention
*/
DWORD GetLevel() const; /**
* SetLevel
*
* @param DWORD dwLevel <IN>
* @return
* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;
* @attention
*/
VOID SetLevel(DWORD dwLevel); /**
* GetData
*
* @param
* @return T
* @note
* @attention
*/
T GetData() const; /**
* SetData
*
* @param const T& tTemplate <IN>
* @return
* @note
* @attention
*/
VOID SetData(const T& tTemplate); /**
* GetParent
*
* @param
* @return AL_TreeNodeBinSeq<T>*
* @note parent node pointer, not to manager memory
* @attention
*/
AL_TreeNodeBinSeq<T>* GetParent() const; /**
* SetParent
*
* @param DWORD dwIndex <IN>
* @param AL_TreeNodeBinSeq<T>* pParent <IN>
* @return BOOL
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the index (from the left of parent's child ) [0x00: left child, 0x01: right child]
*/
BOOL SetParent(DWORD dwIndex, AL_TreeNodeBinSeq<T>* pParent); /**
* SetParentLeft
*
* @param AL_TreeNodeBinSeq<T>* pParent <IN>
* @return BOOL
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the left (from the left of parent's child )
*/
BOOL SetParentLeft(AL_TreeNodeBinSeq<T>* pParent); /**
* SetParentRight
*
* @param AL_TreeNodeBinSeq<T>* pParent <IN>
* @return BOOL
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the right (from the right of parent's child )
*/
BOOL SetParentRight(AL_TreeNodeBinSeq<T>* pParent); /**
* Insert
*
* @param DWORD dwIndex <IN>
* @param AL_TreeNodeBinSeq<T>* pInsertChild <IN>
* @return BOOL
* @note inset the const AL_TreeNodeBinSeq<T>* into the child notes at the position [0x00: left child, 0x01: right child]
* @attention
*/
BOOL Insert(DWORD dwIndex, AL_TreeNodeBinSeq<T>* pInsertChild); /**
* InsertLeft
*
* @param AL_TreeNodeBinSeq<T>* pInsertChild <IN>
* @return BOOL
* @note inset the const AL_TreeNodeBinSeq<T>* into the child notes at the left
* @attention
*/
BOOL InsertLeft(AL_TreeNodeBinSeq<T>* pInsertChild); /**
* InsertRight
*
* @param AL_TreeNodeBinSeq<T>* pInsertChild <IN>
* @return BOOL
* @note inset the const AL_TreeNodeBinSeq<T>* into the child notes at the right
* @attention
*/
BOOL InsertRight(AL_TreeNodeBinSeq<T>* pInsertChild); /**
* Remove
*
* @param AL_TreeNodeBinSeq<T>* pRemoveChild
* @return BOOL
* @note remove the notes in the child
* @attention
*/
BOOL Remove(AL_TreeNodeBinSeq<T>* pRemoveChild); /**
* Remove
*
* @param DWORD dwIndex <IN>
* @return BOOL
* @note remove the child notes at the position [0x00: left child, 0x01: right child]
* @attention
*/
BOOL Remove(DWORD dwIndex); /**
* RemoveLeft
*
* @param
* @return BOOL
* @note remove the child notes at the left
* @attention
*/
BOOL RemoveLeft(); /**
* RemoveRight
*
* @param
* @return BOOL
* @note remove the child notes at the right
* @attention
*/
BOOL RemoveRight(); /**
* GetChildLeft
*
* @param
* @return AL_TreeNodeBinSeq<T>*
* @note
* @attention
*/
AL_TreeNodeBinSeq<T>* GetChildLeft() const; /**
* GetChildRight
*
* @param
* @return AL_TreeNodeBinSeq<T>*
* @note
* @attention
*/
AL_TreeNodeBinSeq<T>* GetChildRight() const; /**
* GetDegree
*
* @param
* @return DWORD
* @note degree node: A node of the subtree containing the number is called the node degree;
* @attention
*/
DWORD GetDegree() const; /**
* IsLeaf
*
* @param
* @return BOOL
* @note leaf nodes or terminal nodes: degree 0 are called leaf nodes;
* @attention
*/
BOOL IsLeaf() const; /**
* IsBranch
*
* @param
* @return BOOL
* @note non-terminal node or branch node: node degree is not 0;
* @attention
*/
BOOL IsBranch() const; /**
* IsParent
*
* @param const AL_TreeNodeBinSeq<T>* pChild <IN>
* @return BOOL
* @note parent node or the parent node: If a node contains a child node, this node is called its child
* @attention
*/
BOOL IsParent(const AL_TreeNodeBinSeq<T>* pChild) const; /**
* GetSibling
*
* @param AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listSibling <OUT>
* @return BOOL
* @note sibling nodes: nodes with the same parent node is called mutual sibling;
* @attention
*/
BOOL GetSibling(AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listSibling) const; /**
* GetAncestor
*
* @param AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listAncestor <OUT>
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention
*/
BOOL GetAncestor(AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listAncestor) const; /**
* GetDescendant
*
* @param AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listDescendant <OUT>
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention
*/
BOOL GetDescendant(AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listDescendant) const; protected:
public:
friend class AL_TreeBinSeq<T>; /**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
AL_TreeNodeBinSeq(); /**
* Construction
*
* @param const T& tTemplate <IN>
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
AL_TreeNodeBinSeq(const T& tTemplate); /**
*Copy Construct
*
* @param const AL_TreeNodeBinSeq<T>& cAL_TreeNodeBinSeq
* @return
*/
AL_TreeNodeBinSeq(const AL_TreeNodeBinSeq<T>& cAL_TreeNodeBinSeq); /**
*Assignment
*
* @param const AL_TreeNodeBinSeq<T>& cAL_TreeNodeBinSeq
* @return AL_TreeNodeBinSeq<T>&
*/
AL_TreeNodeBinSeq<T>& operator = (const AL_TreeNodeBinSeq<T>& cAL_TreeNodeBinSeq); public:
protected:
private:
DWORD m_dwLevel; //Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;
T m_data; //the friend class can use it directly AL_TreeNodeBinSeq<T>* m_pParent; //Parent position
AL_TreeNodeBinSeq<T>* m_pChildLeft; //Child tree node left
AL_TreeNodeBinSeq<T>* m_pChildRight; //Child tree node right
}; ///////////////////////////////////////////////////////////////////////////
// AL_TreeNodeBinSeq
/////////////////////////////////////////////////////////////////////////// /**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
template<typename T>
AL_TreeNodeBinSeq<T>::AL_TreeNodeBinSeq():
m_dwLevel(0x00),
m_pParent(NULL),
m_pChildLeft(NULL),
m_pChildRight(NULL)
{ } /**
* Construction
*
* @param const T& tTemplate <IN>
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
template<typename T>
AL_TreeNodeBinSeq<T>::AL_TreeNodeBinSeq(const T& tTemplate):
m_dwLevel(0x00),
m_data(tTemplate),
m_pParent(NULL),
m_pChildLeft(NULL),
m_pChildRight(NULL)
{ } /**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
template<typename T>
AL_TreeNodeBinSeq<T>::~AL_TreeNodeBinSeq()
{
//it doesn't matter to clear the pointer or not.
m_dwLevel = 0x00;
m_pParent = NULL;
m_pChildLeft = NULL;
m_pChildRight = NULL;
} /**
* GetLevel
*
* @param
* @return DWORD
* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;
* @attention
*/
template<typename T> DWORD
AL_TreeNodeBinSeq<T>::GetLevel() const
{
return m_dwLevel;
} /**
* SetLevel
*
* @param DWORD dwLevel <IN>
* @return
* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;
* @attention
*/
template<typename T> VOID
AL_TreeNodeBinSeq<T>::SetLevel(DWORD dwLevel)
{
m_dwLevel = dwLevel;
} /**
* GetData
*
* @param
* @return T
* @note
* @attention
*/
template<typename T> T
AL_TreeNodeBinSeq<T>::GetData() const
{
return m_data;
} /**
* SetData
*
* @param const T& tTemplate <IN>
* @return
* @note
* @attention
*/
template<typename T> VOID
AL_TreeNodeBinSeq<T>::SetData(const T& tTemplate)
{
m_data = tTemplate;
} /**
* GetParent
*
* @param
* @return AL_TreeNodeBinSeq<T>*
* @note parent node pointer, not to manager memory
* @attention
*/
template<typename T> AL_TreeNodeBinSeq<T>*
AL_TreeNodeBinSeq<T>::GetParent() const
{
return m_pParent;
} /**
* SetParent
*
* @param DWORD dwIndex <IN>
* @param AL_TreeNodeBinSeq<T>* pParent <IN>
* @return BOOL
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the index (from the left of parent's child ) [0x00: left child, 0x01: right child]
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::SetParent(DWORD dwIndex, AL_TreeNodeBinSeq<T>* pParent)
{
if (NULL == pParent) {
return FALSE;
} BOOL bSetParent = FALSE;
bSetParent = pParent->Insert(dwIndex, this);
if (TRUE == bSetParent) {
//current node insert to the parent successfully
if (NULL != m_pParent) {
//current node has parent
m_pParent->Remove(this);
}
m_pParent = pParent;
}
return bSetParent;
} /**
* SetParentLeft
*
* @param AL_TreeNodeBinSeq<T>* pParent <IN>
* @return
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the left (from the left of parent's child )
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::SetParentLeft(AL_TreeNodeBinSeq<T>* pParent)
{
return SetParent(0x00, pParent);
} /**
* SetParentRight
*
* @param AL_TreeNodeBinSeq<T>* pParent <IN>
* @return
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the right (from the right of parent's child )
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::SetParentRight(AL_TreeNodeBinSeq<T>* pParent)
{
return SetParent(0x01, pParent);
} /**
* Insert
*
* @param DWORD dwIndex <IN>
* @param AL_TreeNodeBinSeq<T>* pInsertChild <IN>
* @return BOOL
* @note inset the const AL_TreeNodeBinSeq<T>* into the child notes at the position [0x00: left child, 0x01: right child]
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::Insert(DWORD dwIndex, AL_TreeNodeBinSeq<T>* pInsertChild)
{
if (0x01 < dwIndex || NULL == pInsertChild) {
return FALSE;
} BOOL bInsert = FALSE;
if (0x00 == dwIndex && NULL == m_pChildLeft) {
//left and the child left not exist
m_pChildLeft = pInsertChild;
bInsert = TRUE;
}
else if (0x01 == dwIndex && NULL == m_pChildRight) {
//right and the child right not exist
m_pChildRight = pInsertChild;
bInsert = TRUE;
}
else {
//no case
bInsert = FALSE;
} if (TRUE == bInsert) {
if (GetLevel()+1 != pInsertChild->GetLevel()) {
//deal with the child level
INT iLevelDiff = pInsertChild->GetLevel() - GetLevel(); AL_ListSeq<AL_TreeNodeBinSeq<T>*> listDescendant;
if (FALSE == GetDescendant(listDescendant)) {
return FALSE;
}
AL_TreeNodeBinSeq<T>* pDescendant = NULL;
for (DWORD dwCnt=0; dwCnt<listDescendant.Length(); dwCnt++) {
if (TRUE == listDescendant.Get(pDescendant, dwCnt)) {
if (NULL != pDescendant) {
//set child level
pDescendant->SetLevel(pDescendant->GetLevel()-iLevelDiff+1);
}
else {
//error
return FALSE;
}
}
else {
//error
return FALSE;
}
}
}
//child node insert to the current successfully
pInsertChild->m_pParent = this;
}
return bInsert;
} /**
* InsertLeft
*
* @param AL_TreeNodeBinSeq<T>* pInsertChild <IN>
* @return BOOL
* @note inset the const AL_TreeNodeBinSeq<T>* into the child notes at the left
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::InsertLeft(AL_TreeNodeBinSeq<T>* pInsertChild)
{
return Insert(0x00, pInsertChild);
} /**
* InsertRight
*
* @param AL_TreeNodeBinSeq<T>* pInsertChild <IN>
* @return BOOL
* @note inset the const AL_TreeNodeBinSeq<T>* into the child notes at the right
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::InsertRight(AL_TreeNodeBinSeq<T>* pInsertChild)
{
return Insert(0x01, pInsertChild);
} /**
* Remove
*
* @param AL_TreeNodeBinSeq<T>* pRemoveChild
* @return BOOL
* @note remove the notes in the child
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::Remove(AL_TreeNodeBinSeq<T>* pRemoveChild)
{
BOOL bRemove = FALSE;
if (m_pChildLeft == pRemoveChild) {
m_pChildLeft = NULL;
bRemove = TRUE;
}
else if (m_pChildRight == pRemoveChild) {
m_pChildRight = NULL;
bRemove = TRUE;
}
else {
bRemove = FALSE;
}
return bRemove;
} /**
* Remove
*
* @param DWORD dwIndex <IN>
* @return BOOL
* @note remove the child notes at the position [0x00: left child, 0x01: right child]
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::Remove(DWORD dwIndex)
{
AL_TreeNodeBinSeq<T>* pRemoveChild = NULL;
if (0x00 == dwIndex) {
pRemoveChild = m_pChildLeft;
}
else if (0x01 == dwIndex) {
pRemoveChild = m_pChildRight;
}
else {
return FALSE;
} return Remove(pRemoveChild);
} /**
* RemoveLeft
*
* @param
* @return BOOL
* @note remove the child notes at the left
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::RemoveLeft()
{
return Remove(m_pChildLeft);
} /**
* RemoveRight
*
* @param
* @return BOOL
* @note remove the child notes at the right
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::RemoveRight()
{
return Remove(m_pChildRight);
} /**
* GetChildLeft
*
* @param
* @return AL_TreeNodeBinSeq<T>*
* @note
* @attention
*/
template<typename T> AL_TreeNodeBinSeq<T>*
AL_TreeNodeBinSeq<T>::GetChildLeft() const
{
return m_pChildLeft;
} /**
* GetChildRight
*
* @param
* @return AL_TreeNodeBinSeq<T>*
* @note
* @attention
*/
template<typename T> AL_TreeNodeBinSeq<T>*
AL_TreeNodeBinSeq<T>::GetChildRight() const
{
return m_pChildRight;
} /**
* GetDegree
*
* @param
* @return DWORD
* @note degree node: A node of the subtree containing the number is called the node degree;
* @attention
*/
template<typename T> DWORD
AL_TreeNodeBinSeq<T>::GetDegree() const
{
DWORD dwDegree = 0x00;
if (NULL != m_pChildLeft) {
dwDegree++;
}
if (NULL != m_pChildRight) {
dwDegree++;
} return dwDegree;
} /**
* IsLeaf
*
* @param
* @return BOOL
* @note leaf nodes or terminal nodes: degree 0 are called leaf nodes;
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::IsLeaf() const
{
return (0x00 == GetDegree()) ? TRUE:FALSE;
} /**
* IsBranch
*
* @param
* @return BOOL
* @note non-terminal node or branch node: node degree is not 0;
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::IsBranch() const
{
return (0x00 != GetDegree()) ? TRUE:FALSE;
} /**
* IsParent
*
* @param const AL_TreeNodeBinSeq<T>* pChild <IN>
* @return BOOL
* @note parent node or the parent node: If a node contains a child node, this node is called its child
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::IsParent(const AL_TreeNodeBinSeq<T>* pChild) const
{
if (NULL == pChild) {
return FALSE;
}
// AL_TreeNodeBinSeq<T>* pCompare = NULL;
// for (DWORD dwCnt=0; dwCnt<GetDegree(); dwCnt++) {
// if (TRUE == m_listChild.Get(pCompare, dwCnt)) {
// if (pCompare == pChild) {
// //find the child
// return TRUE;
// }
// }
// }
// return FALSE; if (this == pChild->m_pParent) {
return TRUE;
}
return FALSE;
} /**
* GetSibling
*
* @param AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listSibling <OUT>
* @return BOOL
* @note sibling nodes: nodes with the same parent node is called mutual sibling;
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::GetSibling(AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listSibling) const
{
BOOL bSibling = FALSE;
if (NULL == m_pParent) {
//not parent node
return bSibling;
} listSibling.Clear(); AL_TreeNodeBinSeq<T>* pParentChild = GetChildLeft();
if (NULL != pParentChild) {
if (pParentChild != this) {
//not itself
listSibling.InsertEnd(pParentChild);
bSibling = TRUE;
}
} pParentChild = GetChildRight();
if (NULL != pParentChild) {
if (pParentChild != this) {
//not itself
listSibling.InsertEnd(pParentChild);
bSibling = TRUE;
}
} return bSibling;
} /**
* GetAncestor
*
* @param AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listAncestor <OUT>
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::GetAncestor(AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listAncestor) const
{
if (NULL == m_pParent) {
//not parent node
return FALSE;
} listAncestor.Clear();
AL_TreeNodeBinSeq<T>* pParent = m_pParent;
while (NULL != pParent) {
listAncestor.InsertEnd(pParent);
pParent = pParent->m_pParent;
}
return TRUE;
} /**
* GetDescendant
*
* @param AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listDescendant <OUT>
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention
*/
template<typename T> BOOL
AL_TreeNodeBinSeq<T>::GetDescendant(AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listDescendant) const
{
if (TRUE == IsLeaf()) {
//child node
return FALSE;
} listDescendant.Clear();
AL_TreeNodeBinSeq<T>* pDescendant = GetChildLeft();
if (NULL != pDescendant) {
listDescendant.InsertEnd(pDescendant);
} pDescendant = GetChildRight();
if (NULL != pDescendant) {
listDescendant.InsertEnd(pDescendant);
} //loop the all node in listDescendant
DWORD dwDescendantLoop = 0x00;
AL_TreeNodeBinSeq<T>* pDescendantLoop = NULL;
while (TRUE == listDescendant.Get(pDescendant, dwDescendantLoop)) {
dwDescendantLoop++;
if (NULL != pDescendant) {
pDescendantLoop = pDescendant->GetChildLeft();
if (NULL != pDescendantLoop) {
listDescendant.InsertEnd(pDescendantLoop);
} pDescendantLoop = pDescendant->GetChildRight();
if (NULL != pDescendantLoop) {
listDescendant.InsertEnd(pDescendantLoop);
}
}
else {
//error
return FALSE;
}
}
return TRUE;
} /**
*Assignment
*
* @param const AL_TreeNodeBinSeq<T>& cAL_TreeNodeBinSeq
* @return AL_TreeNodeBinSeq<T>&
*/
template<typename T> AL_TreeNodeBinSeq<T>&
AL_TreeNodeBinSeq<T>::operator = (const AL_TreeNodeBinSeq<T>& cAL_TreeNodeBinSeq)
{
m_dwLevel = cAL_TreeNodeBinSeq.m_dwLevel;
m_data = cAL_TreeNodeBinSeq.m_data;
m_pParent = cAL_TreeNodeBinSeq.m_pParent;
m_pChildLeft = cAL_TreeNodeBinSeq.m_pChildLeft;
m_pChildRight = cAL_TreeNodeBinSeq.m_pChildRight;
return *this;
}
#endif // CXX_AL_TREENODEBINSEQ_H
/* EOF */
AL_TreeBinSeq.h
/**
@(#)$Id: AL_TreeBinSeq.h 55 2013-09-24 06:58:07Z xiaoting $
@brief Tree (tree) that contains n (n> 0) nodes of a finite set, where:
(1) Each element is called node (node);
(2) there is a particular node is called the root node or root (root).
(3) In addition to the remaining data elements other than the root node is divided into m (m ≥ 0) disjoint set of T1, T2, ......
Tm-1, wherein each set of Ti (1 <= i <= m ) itself is a tree, the original tree is called a subtree (subtree). Trees can also be defined as: the tree is a root node and several sub-tree consisting of stars. And a tree is a set defined on the
set consisting of a relationship. Elements in the collection known as a tree of nodes, the defined relationship is called
parent-child relationship. Parent-child relationship between the nodes of the tree establishes a hierarchy. In this there is a
hierarchy node has a special status, this node is called the root of the tree, otherwise known as root. We can give form to the tree recursively defined as follows:
Single node is a tree, the roots is the node itself.
Let T1, T2, .., Tk is a tree, the root node are respectively n1, n2, .., nk. With a new node n as n1, n2, .., nk's father, then
get a new tree node n is the new root of the tree. We call n1, n2, .., nk is a group of siblings, they are sub-node n junction.
We also said that n1, n2, .., nk is the sub-tree node n. Empty tree is also called the empty tree. Air no node in the tree. The related concepts of tree
1. Degree of tree: a tree, the maximum degree of the node of the tree is called degree;
2. Height or depth of the tree: the maximum level of nodes in the tree;
3. Forests: the m (m> = 0) disjoint trees set of trees called forest; The related concepts of tree node
1.degree degree node: A node of the subtree containing the number is called the node degree;
2.leaf leaf nodes or terminal nodes: degree 0 are called leaf nodes;
3.branch non-terminal node or branch node: node degree is not 0;
4.parent parent node or the parent node: If a node contains a child node, this node is called its child node's parent;
5.child child node or child node: A node subtree containing the root node is called the node's children;
6.slibing sibling nodes: nodes with the same parent node is called mutual sibling;
7.ancestor ancestor node: from the root to the node through all the nodes on the branch;
8.descendant descendant nodes: a node in the subtree rooted at any node is called the node's descendants. ////////////////////////////////Binary Tree//////////////////////////////////////////
In computer science, a binary tree is that each node has at most two sub-trees ordered tree. Usually the root of the subtree is
called "left subtree" (left subtree) and the "right subtree" (right subtree). Binary tree is often used as a binary search tree
and binary heap or a binary sort tree. Binary tree each node has at most two sub-tree (does not exist a degree greater than two
nodes), left and right sub-tree binary tree of the points, the order can not be reversed. Binary i-th layer of at most 2 power
nodes i -1; binary tree of depth k at most 2 ^ (k) -1 nodes; for any binary tree T, if it is the terminal nodes (i.e. leaf nodes)
is, the nodes of degree 2 is, then = + 1. ////////////////////////////////Complete Binary Tree//////////////////////////////////////////
If set binary height of h, the h layer in addition, the other layers (1 ~ h-1) has reached the maximum number of nodes, right to
left, the h-layer node number of consecutive missing, this is a complete binary tree . ////////////////////////////////Full Binary Tree//////////////////////////////////////////
A binary tree of height h is 2 ^ h-1 element is called a full binary tree. ////////////////////////////////Sequential storage structure//////////////////////////////////////////
Using a set of addresses in the computer storage unit sequentially stores continuous linear form of individual data elements, called
the linear order of the table storage structure. Sequential storage structure is a type of a storage structure, the structure is the logically adjacent nodes stored in the physical
location of the adjacent memory cells, the logical relationship between nodes from the storage unit to reflect the adjacency.
Storage structure thus obtained is stored in order structure, usually by means of sequential storage structure computer programming
language (e.g., c / c) of the array to describe. The main advantage of the storage structure in order to save storage space, because the allocation to the data storage unit storing
all nodes with data (without regard to c / c language in the array size required for the case), the logical relationship between
the nodes does not take additional storage space. In this method, the node can be realized on a random access, that is, each node
corresponds to a number, the number can be calculated directly from the node out of the memory address. However, the main
disadvantage of sequential storage method is easy to modify the node insert, delete operations, may have to move a series of nodes.
Benefits:
Random Access table elements.
Disadvantages:
insert and delete operations need to move elements. @Author $Author: xiaoting $
@Date $Date: 2013-09-24 14:58:07 +0800 (周二, 24 九月 2013) $
@Revision $Revision: 55 $
@URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeBinSeq.h $
@Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeBinSeq.h 55 2013-09-24 06:58:07Z xiaoting $
*/ #ifndef CXX_AL_TREEBINSEQ_H
#define CXX_AL_TREEBINSEQ_H #ifndef CXX_AL_LISTSEQ_H
#include "AL_ListSeq.h"
#endif #ifndef CXX_AL_QUEUESEQ_H
#include "AL_QueueSeq.h"
#endif #ifndef CXX_AL_TREENODEBINSEQ_H
#include "AL_TreeNodeBinSeq.h"
#endif #ifndef CXX_AL_STACKSEQ_H
#include "AL_StackSeq.h"
#endif ///////////////////////////////////////////////////////////////////////////
// AL_TreeBinSeq
/////////////////////////////////////////////////////////////////////////// template<typename T>
class AL_TreeBinSeq
{
public:
static const DWORD TREESEQ_DEFAULTSIZE = 100;
static const DWORD TREESEQ_MAXSIZE = 0xffffffff; /**
* Construction
*
* @param DWORD dwSize (default value: TREESEQ_DEFAULTSIZE)
* @return
* @note
* @attention
*/
AL_TreeBinSeq(DWORD dwSize = TREESEQ_DEFAULTSIZE); /**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
~AL_TreeBinSeq(); /**
* IsEmpty
*
* @param VOID
* @return BOOL
* @note the tree has data?
* @attention
*/
BOOL IsEmpty() const; /**
* GetRootNode
*
* @param
* @return const AL_TreeNodeBinSeq<T>*
* @note Get the root data
* @attention
*/
const AL_TreeNodeBinSeq<T>* GetRootNode() const; /**
* GetDegree
*
* @param
* @return DWORD
* @note Degree of tree: a tree, the maximum degree of the node of the tree is called degree;
* @attention
*/
DWORD GetDegree() const; /**
* GetHeight
*
* @param
* @return DWORD
* @note Height or depth of the tree: the maximum level of nodes in the tree;
* @attention
*/
DWORD GetHeight() const; /**
* GetNodesNum
*
* @param
* @return DWORD
* @note get the notes number of the tree
* @attention
*/
DWORD GetNodesNum() const; /**
* Clear
*
* @param
* @return
* @note
* @attention
*/
VOID Clear(); /**
* PreOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note Pre-order traversal
* @attention
*/
BOOL PreOrderTraversal(AL_ListSeq<T>& listOrder) const; /**
* InOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note In-order traversal
* @attention
*/
BOOL InOrderTraversal(AL_ListSeq<T>& listOrder) const; /**
* PostOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note Post-order traversal
* @attention
*/
BOOL PostOrderTraversal(AL_ListSeq<T>& listOrder) const; /**
* LevelOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note Level-order traversal
* @attention
*/
BOOL LevelOrderTraversal(AL_ListSeq<T>& listOrder) const; /**
* GetSiblingAtNode
*
* @param AL_ListSeq<T>& listSibling <OUT>
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return BOOL
* @note sibling nodes: nodes with the same parent node is called mutual sibling;
* @attention the current tree node must be in the tree
*/
BOOL GetSiblingAtNode(AL_ListSeq<T>& listSibling, const AL_TreeNodeBinSeq<T>* pCurTreeNode) const; /**
* GetAncestorAtNode
*
* @param AL_ListSeq<T>& listAncestor <OUT>
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention the current tree node must be in the tree
*/
BOOL GetAncestorAtNode(AL_ListSeq<T>& listAncestor, const AL_TreeNodeBinSeq<T>* pCurTreeNode) const; /**
* GetDescendantAtNode
*
* @param AL_ListSeq<T>& listDescendant <OUT>
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention the current tree node must be in the tree
*/
BOOL GetDescendantAtNode(AL_ListSeq<T>& listDescendant, const AL_TreeNodeBinSeq<T>* pCurTreeNode) const; /**
* InsertRoot
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note
* @attention
*/
BOOL InsertRoot(const T& tTemplate); /**
* InsertLeftAtNode
*
* @param AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note insert the tTemplate as child tree node to the current tree node (pCurTreeNode) at the position (left)
* @attention if NULL == pCurTreeNode, it will be insert as root tree node, the current tree node must be in the tree
*/
BOOL InsertLeftAtNode(AL_TreeNodeBinSeq<T>* pCurTreeNode, const T& tTemplate); /**
* InsertRightAtNode
*
* @param AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note insert the tTemplate as child tree node to the current tree node (pCurTreeNode) at the position (right)
* @attention if NULL == pCurTreeNode, it will be insert as root tree node, the current tree node must be in the tree
*/
BOOL InsertRightAtNode(AL_TreeNodeBinSeq<T>* pCurTreeNode, const T& tTemplate); /**
* RemoveNode
*
* @param AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return BOOL
* @note
* @attention the current tree node must be in the tree
*/
BOOL RemoveNode(AL_TreeNodeBinSeq<T>* pCurTreeNode); /**
* GetChildNodeLeftAtNode
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return const AL_TreeNodeBinSeq<T>*
* @note get the current tree node (pCurTreeNode)'s child node at the position (left)
* @attention the current tree node must be in the tree
*/
const AL_TreeNodeBinSeq<T>* GetChildNodeLeftAtNode(const AL_TreeNodeBinSeq<T>* pCurTreeNode) const; /**
* GetChildNodeRightAtNode
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return const AL_TreeNodeBinSeq<T>*
* @note get the current tree node (pCurTreeNode)'s child node at the position (right)
* @attention the current tree node must be in the tree
*/
const AL_TreeNodeBinSeq<T>* GetChildNodeRightAtNode(const AL_TreeNodeBinSeq<T>* pCurTreeNode) const; /**
* IsCompleteTreeBin
*
* @param
* @return BOOL
* @note Is Complete Binary Tree
* @attention If set binary height of h, the h layer in addition, the other layers (1 ~ h-1) has reached the maximum number of
nodes, right to left, the h-layer node number of consecutive missing, this is a complete binary tree .
*/
BOOL IsCompleteTreeBin() const; /**
* IsFullTreeBin
*
* @param
* @return BOOL
* @note Is Full Binary Tree
* @attention A binary tree of height h is 2 ^ h-1 element is called a full binary tree.
*/
BOOL IsFullTreeBin() const; protected:
private: /**
* InsertAtNode
*
* @param AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param DWORD dwIndex <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note insert the tTemplate as child tree node to the current tree node (pCurTreeNode) at the position (dwIndex)
* @attention if NULL == pCurTreeNode, it will be insert as root tree node, the current tree node must be in the tree
*/
BOOL InsertAtNode(AL_TreeNodeBinSeq<T>* pCurTreeNode, DWORD dwIndex, const T& tTemplate); /**
* PreOrderTraversal
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param AL_ListSeq<T>& listOrder <OUT>
* @return VOID
* @note Pre-order traversal
* @attention Recursion Traversal
*/
VOID PreOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const; /**
* InOrderTraversal
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param AL_ListSeq<T>& listOrder <OUT>
* @return VOID
* @note In-order traversal
* @attention Recursion Traversal
*/
VOID InOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const; /**
* PostOrderTraversal
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param AL_ListSeq<T>& listOrder <OUT>
* @return VOID
* @note Post-order traversal
* @attention Recursion Traversal
*/
VOID PostOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const; /**
* GetBuffer
*
* @param VOID
* @return VOID
* @note get the work buffer
* @attention when the buffer is not enough, it will become to double
*/
VOID GetBuffer(); /**
* IsFull
*
* @param VOID
* @return BOOL
* @note the buffer is full?
* @attention
*/
BOOL IsFull() const; /**
*Copy Construct
*
* @param const AL_TreeBinSeq<T>& cAL_TreeBinSeq
* @return
*/
AL_TreeBinSeq(const AL_TreeBinSeq<T>& cAL_TreeBinSeq); /**
*Assignment
*
* @param const AL_TreeBinSeq<T>& cAL_TreeBinSeq
* @return AL_TreeBinSeq<T>&
*/
AL_TreeBinSeq<T>& operator = (const AL_TreeBinSeq<T>& cAL_TreeBinSeq); public:
protected:
private:
AL_TreeNodeBinSeq<T>* m_pTreeNode;
DWORD m_dwMaxSize;
DWORD m_dwUsed; DWORD m_dwDegree;
DWORD m_dwHeight;
DWORD m_dwNumNodes;
AL_TreeNodeBinSeq<T>* m_pRootNode;
}; ///////////////////////////////////////////////////////////////////////////
// AL_TreeBinSeq
/////////////////////////////////////////////////////////////////////////// /**
* Construction
*
* @param DWORD dwSize (default value: TREESEQ_DEFAULTSIZE)
* @return
* @note
* @attention
*/
template<typename T>
AL_TreeBinSeq<T>::AL_TreeBinSeq(DWORD dwSize):
m_pTreeNode(NULL),
m_dwMaxSize(dwSize),
m_dwUsed(0x00),
m_dwDegree(0xffffffff),
m_dwHeight(0x00),
m_dwNumNodes(0x00),
m_pRootNode(NULL)
{
if (0x00 == m_dwMaxSize) {
//for memory deal
m_dwMaxSize = 1;
}
GetBuffer();
} /**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
template<typename T>
AL_TreeBinSeq<T>::~AL_TreeBinSeq()
{
if (NULL != m_pTreeNode) {
delete[] m_pTreeNode;
m_pTreeNode = NULL;
}
m_dwMaxSize = 0x00;
m_dwUsed = 0x00;
m_dwDegree = 0xffffffff;
m_dwHeight = 0x00;
m_dwNumNodes = 0x00;
m_pRootNode = NULL;
} /**
* IsEmpty
*
* @param VOID
* @return BOOL
* @note the tree has data?
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::IsEmpty() const
{
return (0x00 == m_dwNumNodes) ? TRUE:FALSE;
} /**
* GetRootNode
*
* @param
* @return const AL_TreeNodeBinSeq<T>*
* @note Get the root data
* @attention
*/
template<typename T> const AL_TreeNodeBinSeq<T>*
AL_TreeBinSeq<T>::GetRootNode() const
{
return m_pRootNode;
} /**
* GetDegree
*
* @param
* @return DWORD
* @note Degree of tree: a tree, the maximum degree of the node of the tree is called degree;
* @attention
*/
template<typename T> DWORD
AL_TreeBinSeq<T>::GetDegree() const
{
return m_dwDegree;
} /**
* GetHeight
*
* @param
* @return DWORD
* @note Height or depth of the tree: the maximum level of nodes in the tree;
* @attention
*/
template<typename T> DWORD
AL_TreeBinSeq<T>::GetHeight() const
{
return m_dwHeight;
} /**
* GetNodesNum
*
* @param
* @return DWORD
* @note get the notes number of the tree
* @attention
*/
template<typename T> DWORD
AL_TreeBinSeq<T>::GetNodesNum() const
{
return m_dwNumNodes;
} /**
* Clear
*
* @param
* @return
* @note
* @attention
*/
template<typename T> VOID
AL_TreeBinSeq<T>::Clear()
{
m_dwUsed = 0x00;
m_dwDegree = 0xffffffff;
m_dwHeight = 0x00;
m_dwNumNodes = 0x00;
m_pRootNode = NULL;
} /**
* PreOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note Pre-order traversal
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::PreOrderTraversal(AL_ListSeq<T>& listOrder) const
{
if (NULL == m_pRootNode) {
return FALSE;
} listOrder.Clear(); //Recursion Traversal
PreOrderTraversal(m_pRootNode, listOrder);
return TRUE; //Not Recursion Traversal
AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStack;
AL_TreeNodeBinSeq<T>* pTreeNode = m_pRootNode; while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {
while (NULL != pTreeNode) {
listOrder.InsertEnd(pTreeNode->GetData());
if (NULL != pTreeNode->GetChildRight()) {
//push the child right to stack
cStack.Push(pTreeNode->GetChildRight());
}
pTreeNode = pTreeNode->GetChildLeft();
} if (TRUE == cStack.Pop(pTreeNode)) {
if (NULL == pTreeNode) {
return FALSE;
}
}
else {
return FALSE;
} }
return TRUE;
} /**
* InOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note In-order traversal
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::InOrderTraversal(AL_ListSeq<T>& listOrder) const
{
if (NULL == m_pRootNode) {
return FALSE;
} listOrder.Clear(); //Recursion Traversal
InOrderTraversal(m_pRootNode, listOrder);
return TRUE; //Not Recursion Traversal
AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStack;
AL_TreeNodeBinSeq<T>* pTreeNode = m_pRootNode; while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {
while (NULL != pTreeNode) {
cStack.Push(pTreeNode);
pTreeNode = pTreeNode->GetChildLeft();
} if (TRUE == cStack.Pop(pTreeNode)) {
if (NULL != pTreeNode) {
listOrder.InsertEnd(pTreeNode->GetData());
if (NULL != pTreeNode->GetChildRight()){
//child right exist, push the node, and loop it's left child to push
pTreeNode = pTreeNode->GetChildRight();
}
else {
//to pop the node in the stack
pTreeNode = NULL;
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
} return TRUE;
} /**
* PostOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note Post-order traversal
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::PostOrderTraversal(AL_ListSeq<T>& listOrder) const
{
if (NULL == m_pRootNode) {
return FALSE;
} listOrder.Clear(); //Recursion Traversal
PostOrderTraversal(m_pRootNode, listOrder);
return TRUE; //Not Recursion Traversal
AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStack;
AL_TreeNodeBinSeq<T>* pTreeNode = m_pRootNode;
AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStackReturn;
AL_TreeNodeBinSeq<T>* pTreeNodeReturn = NULL; while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {
while (NULL != pTreeNode) {
cStack.Push(pTreeNode);
if (NULL != pTreeNode->GetChildLeft()) {
pTreeNode = pTreeNode->GetChildLeft();
}
else {
//has not left child, get the right child
pTreeNode = pTreeNode->GetChildRight();
}
} if (TRUE == cStack.Pop(pTreeNode)) {
if (NULL != pTreeNode) {
listOrder.InsertEnd(pTreeNode->GetData());
if (NULL != pTreeNode->GetChildLeft() && NULL != pTreeNode->GetChildRight()){
//child right exist
cStackReturn.Top(pTreeNodeReturn);
if (pTreeNodeReturn != pTreeNode) {
listOrder.RemoveAt(listOrder.Length()-1);
cStack.Push(pTreeNode);
cStackReturn.Push(pTreeNode);
pTreeNode = pTreeNode->GetChildRight();
}
else {
//to pop the node in the stack
cStackReturn.Pop(pTreeNodeReturn);
pTreeNode = NULL;
}
}
else {
//to pop the node in the stack
pTreeNode = NULL;
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
} return TRUE;
} /**
* LevelOrderTraversal
*
* @param AL_ListSeq<T>& listOrder <OUT>
* @return BOOL
* @note Level-order traversal
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::LevelOrderTraversal(AL_ListSeq<T>& listOrder) const
{
if (TRUE == IsEmpty()) {
return FALSE;
} if (NULL == m_pRootNode) {
return FALSE;
}
listOrder.Clear();
/*
AL_ListSeq<AL_TreeNodeBinSeq<T>*> listNodeOrder;
listNodeOrder.InsertEnd(m_pRootNode);
//loop the all node
DWORD dwNodeOrderLoop = 0x00;
AL_TreeNodeBinSeq<T>* pNodeOrderLoop = NULL;
AL_TreeNodeBinSeq<T>* pNodeOrderChild = NULL;
while (TRUE == listNodeOrder.Get(pNodeOrderLoop, dwNodeOrderLoop)) {
dwNodeOrderLoop++;
if (NULL != pNodeOrderLoop) {
listOrder.InsertEnd(pNodeOrderLoop->GetData());
pNodeOrderChild = pNodeOrderLoop->GetChildLeft();
if (NULL != pNodeOrderChild) {
queueOrder.Push(pNodeOrderChild);
}
pNodeOrderChild = pNodeOrderLoop->GetChildRight();
if (NULL != pNodeOrderChild) {
queueOrder.Push(pNodeOrderChild);
}
}
else {
//error
return FALSE;
}
}
return TRUE;
*/ AL_QueueSeq<AL_TreeNodeBinSeq<T>*> queueOrder;
queueOrder.Push(m_pRootNode); AL_TreeNodeBinSeq<T>* pNodeOrderLoop = NULL;
AL_TreeNodeBinSeq<T>* pNodeOrderChild = NULL;
while (FALSE == queueOrder.IsEmpty()) {
if (TRUE == queueOrder.Pop(pNodeOrderLoop)) {
if (NULL != pNodeOrderLoop) {
listOrder.InsertEnd(pNodeOrderLoop->GetData());
pNodeOrderChild = pNodeOrderLoop->GetChildLeft();
if (NULL != pNodeOrderChild) {
queueOrder.Push(pNodeOrderChild);
}
pNodeOrderChild = pNodeOrderLoop->GetChildRight();
if (NULL != pNodeOrderChild) {
queueOrder.Push(pNodeOrderChild);
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
}
return TRUE;
} /**
* GetSiblingAtNode
*
* @param AL_ListSeq<T>& listSibling <OUT>
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return BOOL
* @note sibling nodes: nodes with the same parent node is called mutual sibling;
* @attention the current tree node must be in the tree
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::GetSiblingAtNode(AL_ListSeq<T>& listSibling, const AL_TreeNodeBinSeq<T>* pCurTreeNode) const
{
if (NULL == pCurTreeNode) {
return FALSE;
} AL_ListSeq<AL_TreeNodeBinSeq<T>*> listTreeNodeSibling;
if (FALSE == pCurTreeNode->GetSibling(listTreeNodeSibling)) {
return FALSE;
}
//clear listSibling
listSibling.Clear();
AL_TreeNodeBinSeq<T>* pTreeNodeSibling = NULL;
for (DWORD dwCnt=0; dwCnt<listTreeNodeSibling.Length(); dwCnt++) {
if (TRUE == listTreeNodeSibling.Get(pTreeNodeSibling, dwCnt)) {
if (NULL != pTreeNodeSibling) {
//inset the data to listSibling
listSibling.InsertEnd(pTreeNodeSibling->GetData());
}
else {
//error
return FALSE;
}
}
else {
//error
return FALSE;
}
}
return TRUE;
} /**
* GetAncestorAtNode
*
* @param AL_ListSeq<T>& listAncestor <OUT>
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention the current tree node must be in the tree
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::GetAncestorAtNode(AL_ListSeq<T>& listAncestor, const AL_TreeNodeBinSeq<T>* pCurTreeNode) const
{
if (NULL == pCurTreeNode) {
return FALSE;
} AL_ListSeq<AL_TreeNodeBinSeq<T>*> listTreeNodeAncestor;
if (FALSE == pCurTreeNode->GetAncestor(listTreeNodeAncestor)) {
return FALSE;
}
//clear listAncestor
listAncestor.Clear();
AL_TreeNodeBinSeq<T>* pTreeNodeAncestor = NULL;
for (DWORD dwCnt=0; dwCnt<listTreeNodeAncestor.Length(); dwCnt++) {
if (TRUE == listTreeNodeAncestor.Get(pTreeNodeAncestor, dwCnt)) {
if (NULL != pTreeNodeAncestor) {
//inset the data to listSibling
listAncestor.InsertEnd(pTreeNodeAncestor->GetData());
}
else {
//error
return FALSE;
}
}
else {
//error
return FALSE;
}
}
return TRUE;
} /**
* GetDescendantAtNode
*
* @param AL_ListSeq<T>& listDescendant <OUT>
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention the current tree node must be in the tree
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::GetDescendantAtNode(AL_ListSeq<T>& listDescendant, const AL_TreeNodeBinSeq<T>* pCurTreeNode) const
{
if (NULL == pCurTreeNode) {
return FALSE;
} AL_ListSeq<AL_TreeNodeBinSeq<T>*> listTreeNodeDescendant;
if (FALSE == pCurTreeNode->GetDescendant(listTreeNodeDescendant)) {
return FALSE;
}
//clear listAncestor
listDescendant.Clear();
AL_TreeNodeBinSeq<T>* pTreeNodeDescendant = NULL;
for (DWORD dwCnt=0; dwCnt<listTreeNodeDescendant.Length(); dwCnt++) {
if (TRUE == listTreeNodeDescendant.Get(pTreeNodeDescendant, dwCnt)) {
if (NULL != pTreeNodeDescendant) {
//inset the data to listSibling
listDescendant.InsertEnd(pTreeNodeDescendant->GetData());
}
else {
//error
return FALSE;
}
}
else {
//error
return FALSE;
}
}
return TRUE;
} /**
* InsertRoot
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::InsertRoot(const T& tTemplate)
{
return InsertAtNode(NULL, 0x00, tTemplate);
} /**
* InsertLeftAtNode
*
* @param AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note insert the tTemplate as child tree node to the current tree node (pCurTreeNode) at the position (left)
* @attention if NULL == pCurTreeNode, it will be insert as root tree node, the current tree node must be in the tree
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::InsertLeftAtNode(AL_TreeNodeBinSeq<T>* pCurTreeNode, const T& tTemplate)
{
return InsertAtNode(pCurTreeNode, 0x00, tTemplate);
} /**
* InsertRightAtNode
*
* @param AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note insert the tTemplate as child tree node to the current tree node (pCurTreeNode) at the position (right)
* @attention if NULL == pCurTreeNode, it will be insert as root tree node, the current tree node must be in the tree
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::InsertRightAtNode(AL_TreeNodeBinSeq<T>* pCurTreeNode, const T& tTemplate)
{
return InsertAtNode(pCurTreeNode, 0x01, tTemplate);
} /**
* RemoveNode
*
* @param AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return BOOL
* @note
* @attention the current tree node must be in the tree
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::RemoveNode(AL_TreeNodeBinSeq<T>* pCurTreeNode)
{
IsFullTreeBin();
if (NULL == pCurTreeNode) {
return FALSE;
} AL_ListSeq<AL_TreeNodeBinSeq<T>*> listTreeNodeDescendant;
if (FALSE == pCurTreeNode->GetDescendant(listTreeNodeDescendant)) {
return FALSE;
} AL_TreeNodeBinSeq<T>* pTreeNodeDescendant = NULL;
AL_TreeNodeBinSeq<T>* pNodeParent = pCurTreeNode->GetParent();
if (NULL == pNodeParent && m_pRootNode != pNodeParent) {
//not root node and has no parent node
return FALSE;
}
pNodeParent->Remove(pCurTreeNode);
m_dwNumNodes -= (listTreeNodeDescendant.Length() + 1); //loop all the node
listTreeNodeDescendant.Clear();
if (FALSE == m_pRootNode->GetDescendant(listTreeNodeDescendant)) {
return FALSE;
} m_dwDegree = m_pRootNode->GetDegree();
m_dwHeight = m_pRootNode->GetLevel();
for (DWORD dwLoopCnt=0; dwLoopCnt<listTreeNodeDescendant.Length(); dwLoopCnt++) {
if (TRUE == listTreeNodeDescendant.Get(pTreeNodeDescendant, dwLoopCnt)) {
if (NULL != pTreeNodeDescendant) {
if (m_dwDegree < pTreeNodeDescendant->GetDegree()) {
m_dwDegree = pTreeNodeDescendant->GetDegree();
}
if (m_dwHeight < pTreeNodeDescendant->GetLevel()) {
m_dwHeight = pTreeNodeDescendant->GetLevel();
}
}
else {
//error
return FALSE;
}
}
else {
//error
return FALSE;
}
} return TRUE;
} /**
* GetChildNodeLeftAtNode
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return const AL_TreeNodeBinSeq<T>*
* @note get the current tree node (pCurTreeNode)'s child node at the position (left)
* @attention the current tree node must be in the tree
*/
template<typename T> const AL_TreeNodeBinSeq<T>*
AL_TreeBinSeq<T>::GetChildNodeLeftAtNode(const AL_TreeNodeBinSeq<T>* pCurTreeNode) const
{
if (NULL == pCurTreeNode) {
return FALSE;
}
return pCurTreeNode->GetChildLeft();
} /**
* GetChildNodeRightAtNode
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @return const AL_TreeNodeBinSeq<T>*
* @note get the current tree node (pCurTreeNode)'s child node at the position (right)
* @attention
*/
template<typename T> const AL_TreeNodeBinSeq<T>*
AL_TreeBinSeq<T>::GetChildNodeRightAtNode(const AL_TreeNodeBinSeq<T>* pCurTreeNode) const
{
if (NULL == pCurTreeNode) {
return FALSE;
}
return pCurTreeNode->GetChildRight();
} /**
* IsCompleteTreeBin
*
* @param
* @return BOOL
* @note Is Complete Binary Tree
* @attention If set binary height of h, the h layer in addition, the other layers (1 ~ h-1) has reached the maximum number of
nodes, right to left, the h-layer node number of consecutive missing, this is a complete binary tree .
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::IsCompleteTreeBin() const
{
if (TRUE == IsEmpty()) {
return FALSE;
}
if (NULL == m_pRootNode) {
return FALSE;
} AL_TreeNodeBinSeq<T>* pTreeNode;
AL_ListSeq<AL_TreeNodeBinSeq<T>*>& listDescendant;
m_pRootNode->GetDescendant(listDescendant);
BOOL bMissing = FALSE;
for (DWORD dwCnt=0x00; dwCnt<listDescendant->Length(); dwCnt++) {
if (TRUE == listDescendant.Get(pTreeNode, dwCnt)) {
if (NULL != pTreeNode) {
if (m_dwHeight > pTreeNode->GetLevel()) {
//the other layers (1 ~ h-1)
if (NULL == pTreeNode->GetChildLeft() || NULL == pTreeNode->GetChildRight()) {
//left or right child not exist!
return FALSE
}
}
else {
//the h-layer
if (TRUE == bMissing) {
//node number of consecutive missing
if (NULL == pTreeNode->GetChildLeft() || NULL == pTreeNode->GetChildRight()) {
//left or right child not exist!
return FALSE
}
} if (NULL == pTreeNode->GetChildLeft()) {
//left child not exist!
bMissing = TRUE;
if (NULL != pTreeNode->GetChildRight()) {
//right child exist!
return FALSE;
}
}
else {
//left child exist!
if (NULL == pTreeNode->GetChildRight()) {
//right child not exist!
bMissing = TRUE;
}
}
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
} return TRUE;
} /**
* IsFullTreeBin
*
* @param
* @return BOOL
* @note Is Full Binary Tree
* @attention A binary tree of height h is 2 ^ h-1 element is called a full binary tree.
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::IsFullTreeBin() const
{
if (TRUE == IsEmpty()) {
return FALSE;
} DWORD dwTwo = 2;
DWORD dwFullTreeBinNum = 1;
for (DWORD dwFull=0x00; dwFull<GetHeight(); dwFull++) {
dwFullTreeBinNum *= 2;
}
dwFullTreeBinNum -= 1; return (dwFullTreeBinNum == GetNodesNum()) ? TRUE:FALSE;
} /**
* InsertAtNode
*
* @param AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param DWORD dwIndex <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note insert the tTemplate as child tree node to the current tree node (pCurTreeNode) at the position (dwIndex)
* @attention if NULL == pCurTreeNode, it will be insert as root tree node, the current tree node must be in the tree
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::InsertAtNode(AL_TreeNodeBinSeq<T>* pCurTreeNode, DWORD dwIndex, const T& tTemplate)
{
if (TRUE == IsEmpty()) {
if (NULL != pCurTreeNode) {
//error can not insert to the current node pCurTreeNode, is not exist in the tree
return FALSE;
}
else {
m_pTreeNode[m_dwUsed].SetData(tTemplate);
m_pTreeNode[m_dwUsed].SetLevel(0x00); m_pRootNode = &m_pTreeNode[m_dwUsed];
m_dwUsed++;
m_dwDegree = 0x00;
m_dwHeight = 0x00; //empty tree 0xffffffff (-1)
m_dwNumNodes++;
return TRUE;
}
} if (NULL == pCurTreeNode) {
return FALSE;
} if (TRUE == IsFull()) {
// full, need to get more work buffer
//can not support Dynamic Expansion
return FALSE;
GetBuffer();
} //inset to the current tree node
m_pTreeNode[m_dwUsed].SetData(tTemplate);
m_pTreeNode[m_dwUsed].SetLevel(pCurTreeNode->GetLevel() + 1);
if (FALSE == pCurTreeNode->Insert(dwIndex, &m_pTreeNode[m_dwUsed])) {
return FALSE;
} DWORD dwCurNodeDegree = 0x00;
//loop all node to get the current node degree
if (pCurTreeNode->GetDegree() > m_dwDegree) {
m_dwDegree = pCurTreeNode->GetDegree();
} if (m_pTreeNode[m_dwUsed].GetLevel() > m_dwHeight) {
m_dwHeight = m_pTreeNode[m_dwUsed].GetLevel();
}
m_dwUsed++;
m_dwNumNodes++; return TRUE;
} /**
* PreOrderTraversal
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param AL_ListSeq<T>& listOrder <OUT>
* @return VOID
* @note Pre-order traversal
* @attention Recursion Traversal
*/
template<typename T> VOID
AL_TreeBinSeq<T>::PreOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const
{
if (NULL == pCurTreeNode) {
return;
}
//Do Something with root
listOrder.InsertEnd(pCurTreeNode->GetData()); if(NULL != pCurTreeNode->GetChildLeft()) {
PreOrderTraversal(pCurTreeNode->GetChildLeft(), listOrder);
} if(NULL != pCurTreeNode->GetChildRight()) {
PreOrderTraversal(pCurTreeNode->GetChildRight(), listOrder);
}
} /**
* InOrderTraversal
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param AL_ListSeq<T>& listOrder <OUT>
* @return VOID
* @note In-order traversal
* @attention Recursion Traversal
*/
template<typename T> VOID
AL_TreeBinSeq<T>::InOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const
{
if (NULL == pCurTreeNode) {
return;
} if(NULL != pCurTreeNode->GetChildLeft()) {
InOrderTraversal(pCurTreeNode->GetChildLeft(), listOrder);
} //Do Something with root
listOrder.InsertEnd(pCurTreeNode->GetData()); if(NULL != pCurTreeNode->GetChildRight()) {
InOrderTraversal(pCurTreeNode->GetChildRight(), listOrder);
}
} /**
* PostOrderTraversal
*
* @param const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>
* @param AL_ListSeq<T>& listOrder <OUT>
* @return VOID
* @note Post-order traversal
* @attention Recursion Traversal
*/
template<typename T> VOID
AL_TreeBinSeq<T>::PostOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const
{
if (NULL == pCurTreeNode) {
return;
} if(NULL != pCurTreeNode->GetChildLeft()) {
PostOrderTraversal(pCurTreeNode->GetChildLeft(), listOrder);
} if(NULL != pCurTreeNode->GetChildRight()) {
PostOrderTraversal(pCurTreeNode->GetChildRight(), listOrder);
} //Do Something with root
listOrder.InsertEnd(pCurTreeNode->GetData());
} /**
* GetBuffer
*
* @param VOID
* @return VOID
* @note get the work buffer
* @attention when the buffer is not enough, it will become to double
*/
template<typename T> VOID
AL_TreeBinSeq<T>::GetBuffer()
{
if ( (FALSE == IsFull()) && (NULL != m_pTreeNode) ) {
//we do not need to get more buffer
return;
} if (NULL == m_pTreeNode) {
if(0 < m_dwMaxSize){
//get the new work buffer
m_pTreeNode = new AL_TreeNodeBinSeq<T>[m_dwMaxSize];
}
return;
} //we need to get more buffer, store the previous pointer
AL_TreeNodeBinSeq<T>* pLastTpye = NULL; // it will become to double
pLastTpye = m_pTreeNode;
if (TREESEQ_MAXSIZE == m_dwMaxSize) {
//can not get more buffer, please check the application
return;
}
else if (TREESEQ_MAXSIZE/2 < m_dwMaxSize) {
m_dwMaxSize = TREESEQ_MAXSIZE;
}
else {
m_dwMaxSize *= 2;
}
if(0 < m_dwMaxSize){
//get the new work buffer
m_pTreeNode = new AL_TreeNodeBinSeq<T>[m_dwMaxSize];
}
//need to copy the last to the current
for (DWORD dwCpy=0; dwCpy<GetNodesNum(); dwCpy++) {
m_pTreeNode[dwCpy] = pLastTpye[dwCpy];
} //free the last work buffer
delete[] pLastTpye;
pLastTpye = NULL;
} /**
* IsFull
*
* @param VOID
* @return BOOL
* @note the buffer is full?
* @attention
*/
template<typename T> BOOL
AL_TreeBinSeq<T>::IsFull() const
{
return (m_dwMaxSize <= GetNodesNum()) ? TRUE:FALSE;
}
#endif // CXX_AL_TREEBINSEQ_H
/* EOF */
测试代码
#ifdef TEST_AL_TREEBINSEQ
AL_TreeBinSeq<DWORD> cTreeBinSeq(100);
BOOL bEmpty = cTreeBinSeq.IsEmpty();
std::cout<<bEmpty<<std::endl;
const AL_TreeNodeBinSeq<DWORD>* pConstRootNode = cTreeBinSeq.GetRootNode();
AL_TreeNodeBinSeq<DWORD>* pRootNode = const_cast<AL_TreeNodeBinSeq<DWORD>*>(pConstRootNode);
std::cout<<pRootNode<<std::endl;
DWORD dwDegree = cTreeBinSeq.GetDegree();
std::cout<<dwDegree<<std::endl;
DWORD dwHeight = cTreeBinSeq.GetHeight();
std::cout<<dwHeight<<std::endl;
DWORD dwNodesNum = cTreeBinSeq.GetNodesNum();
std::cout<<dwNodesNum<<std::endl; cTreeBinSeq.InsertRoot(0);
pConstRootNode = cTreeBinSeq.GetRootNode();
pRootNode = const_cast<AL_TreeNodeBinSeq<DWORD>*>(pConstRootNode);
std::cout<<pRootNode<<std::endl; cTreeBinSeq.InsertLeftAtNode(pRootNode, 10); const AL_TreeNodeBinSeq<DWORD>* pConstTreeNode = cTreeBinSeq.GetChildNodeLeftAtNode(pRootNode);
AL_TreeNodeBinSeq<DWORD>* pTreeNode = const_cast<AL_TreeNodeBinSeq<DWORD>*>(pConstTreeNode);
std::cout<<pTreeNode<<std::endl; cTreeBinSeq.InsertLeftAtNode(pTreeNode, 20);
cTreeBinSeq.InsertRightAtNode(pTreeNode, 21); const AL_TreeNodeBinSeq<DWORD>* pConstTreeNode20 = cTreeBinSeq.GetChildNodeLeftAtNode(pTreeNode);
AL_TreeNodeBinSeq<DWORD>* pTreeNode20 = const_cast<AL_TreeNodeBinSeq<DWORD>*>(pConstTreeNode20);
std::cout<<pTreeNode<<std::endl; cTreeBinSeq.InsertLeftAtNode(pTreeNode20, 30);
cTreeBinSeq.InsertRightAtNode(pTreeNode20, 31); const AL_TreeNodeBinSeq<DWORD>* pConstTreeNode31 = cTreeBinSeq.GetChildNodeRightAtNode(pConstTreeNode20);
AL_TreeNodeBinSeq<DWORD>* pTreeNode31 = const_cast<AL_TreeNodeBinSeq<DWORD>*>(pConstTreeNode31);
cTreeBinSeq.InsertLeftAtNode(pTreeNode31, 40);
cTreeBinSeq.InsertRightAtNode(pTreeNode31, 41); const AL_TreeNodeBinSeq<DWORD>* pConstTreeNode30 = cTreeBinSeq.GetChildNodeLeftAtNode(pConstTreeNode20);
AL_TreeNodeBinSeq<DWORD>* pTreeNode30 = const_cast<AL_TreeNodeBinSeq<DWORD>*>(pConstTreeNode30);
cTreeBinSeq.InsertRightAtNode(pTreeNode30, 999); const AL_TreeNodeBinSeq<DWORD>* pConstTreeNode999 = cTreeBinSeq.GetChildNodeRightAtNode(pConstTreeNode30);
AL_TreeNodeBinSeq<DWORD>* pTreeNode999 = const_cast<AL_TreeNodeBinSeq<DWORD>*>(pConstTreeNode999);
cTreeBinSeq.InsertLeftAtNode(pTreeNode999, 888); const AL_TreeNodeBinSeq<DWORD>* pConstTreeNode41 = cTreeBinSeq.GetChildNodeRightAtNode(pConstTreeNode31);
AL_TreeNodeBinSeq<DWORD>* pTreeNode41 = const_cast<AL_TreeNodeBinSeq<DWORD>*>(pConstTreeNode41);
cTreeBinSeq.InsertRightAtNode(pTreeNode41, 52); const AL_TreeNodeBinSeq<DWORD>* pConstTreeNode33 = cTreeBinSeq.GetChildNodeRightAtNode(pTreeNode20);
AL_TreeNodeBinSeq<DWORD>* pTreeNode33 = const_cast<AL_TreeNodeBinSeq<DWORD>*>(pConstTreeNode33); if (NULL != pTreeNode) {
std::cout<<pTreeNode->GetLevel()<<" "<<pTreeNode->GetData()<<" "<<pTreeNode->GetDegree()<<std::endl;
std::cout<<pTreeNode->IsLeaf()<<" "<<pTreeNode->IsBranch()<<" "<<pTreeNode->IsParent(pTreeNode)<<" "<<pTreeNode->IsParent(pTreeNode33)<<std::endl;
}
if (NULL != pTreeNode20) {
std::cout<<pTreeNode20->GetLevel()<<" "<<pTreeNode20->GetData()<<" "<<pTreeNode20->GetDegree()<<std::endl;
std::cout<<pTreeNode20->IsLeaf()<<" "<<pTreeNode20->IsBranch()<<" "<<pTreeNode20->IsParent(pTreeNode)<<" "<<pTreeNode20->IsParent(pTreeNode33)<<std::endl;
}
if (NULL != pTreeNode33) {
std::cout<<pTreeNode33->GetLevel()<<" "<<pTreeNode33->GetData()<<" "<<pTreeNode33->GetDegree()<<std::endl;
std::cout<<pTreeNode33->IsLeaf()<<" "<<pTreeNode33->IsBranch()<<" "<<pTreeNode33->IsParent(pTreeNode)<<" "<<pTreeNode33->IsParent(pTreeNode33)<<std::endl;
} const AL_TreeNodeBinSeq<DWORD>* pChild = NULL;
pChild = cTreeBinSeq.GetChildNodeRightAtNode(pTreeNode);
if (NULL != pChild) {
std::cout<<pChild->GetLevel()<<" "<<pChild->GetData()<<" "<<pChild->GetDegree()<<std::endl;
std::cout<<pChild->IsLeaf()<<" "<<pChild->IsBranch()<<" "<<pChild->IsParent(pTreeNode)<<" "<<pChild->IsParent(pTreeNode33)<<std::endl;
}
pChild = cTreeBinSeq.GetChildNodeLeftAtNode(pTreeNode);
if (NULL != pChild) {
std::cout<<pChild->GetLevel()<<" "<<pChild->GetData()<<" "<<pChild->GetDegree()<<std::endl;
std::cout<<pChild->IsLeaf()<<" "<<pChild->IsBranch()<<" "<<pChild->IsParent(pTreeNode)<<" "<<pChild->IsParent(pTreeNode33)<<std::endl;
}
pChild = cTreeBinSeq.GetChildNodeLeftAtNode(pTreeNode);
if (NULL != pChild) {
std::cout<<pChild->GetLevel()<<" "<<pChild->GetData()<<" "<<pChild->GetDegree()<<std::endl;
std::cout<<pChild->IsLeaf()<<" "<<pChild->IsBranch()<<" "<<pChild->IsParent(pTreeNode)<<" "<<pChild->IsParent(pTreeNode33)<<std::endl;
}
pChild = cTreeBinSeq.GetChildNodeRightAtNode(pTreeNode);
if (NULL != pChild) {
std::cout<<pChild->GetLevel()<<" "<<pChild->GetData()<<" "<<pChild->GetDegree()<<std::endl;
std::cout<<pChild->IsLeaf()<<" "<<pChild->IsBranch()<<" "<<pChild->IsParent(pTreeNode)<<" "<<pChild->IsParent(pTreeNode33)<<std::endl;
}
pChild = cTreeBinSeq.GetChildNodeRightAtNode(pTreeNode);
if (NULL != pChild) {
std::cout<<pChild->GetLevel()<<" "<<pChild->GetData()<<" "<<pChild->GetDegree()<<std::endl;
std::cout<<pChild->IsLeaf()<<" "<<pChild->IsBranch()<<" "<<pChild->IsParent(pTreeNode)<<" "<<pChild->IsParent(pTreeNode33)<<std::endl;
} bEmpty = cTreeBinSeq.IsEmpty();
std::cout<<bEmpty<<std::endl;
dwDegree = cTreeBinSeq.GetDegree();
std::cout<<dwDegree<<std::endl;
dwHeight = cTreeBinSeq.GetHeight();
std::cout<<dwHeight<<std::endl;
dwNodesNum = cTreeBinSeq.GetNodesNum();
std::cout<<dwNodesNum<<std::endl; AL_ListSeq<DWORD> cListSeq;
DWORD dwData;
BOOL bSibling = cTreeBinSeq.GetSiblingAtNode(cListSeq, pTreeNode);
if (TRUE == bSibling) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear(); bSibling = cTreeBinSeq.GetSiblingAtNode(cListSeq, pTreeNode20);
if (TRUE == bSibling) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear(); BOOL bAncestor = cTreeBinSeq.GetAncestorAtNode(cListSeq, pRootNode);
if (TRUE == bAncestor) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
} bAncestor = cTreeBinSeq.GetAncestorAtNode(cListSeq, pTreeNode33);
if (TRUE == bAncestor) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear(); BOOL bDescendant = cTreeBinSeq.GetDescendantAtNode(cListSeq, pRootNode);
if (TRUE == bDescendant) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear(); bDescendant = cTreeBinSeq.GetDescendantAtNode(cListSeq, pTreeNode33);
if (TRUE == bDescendant) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear(); BOOL bOrder = cTreeBinSeq.PreOrderTraversal(cListSeq);
if (TRUE == bOrder) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear(); bOrder = cTreeBinSeq.InOrderTraversal(cListSeq);
if (TRUE == bOrder) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear(); bOrder = cTreeBinSeq.PostOrderTraversal(cListSeq);
if (TRUE == bOrder) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear(); bOrder = cTreeBinSeq.LevelOrderTraversal(cListSeq);
if (TRUE == bOrder) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear(); cTreeBinSeq.RemoveNode(pTreeNode20);
bOrder = cTreeBinSeq.LevelOrderTraversal(cListSeq);
if (TRUE == bOrder) {
for (DWORD dwCnt=0; dwCnt<cListSeq.Length(); dwCnt++) {
if (TRUE == cListSeq.Get(dwData, dwCnt)) {
std::cout<<dwData<<", ";
}
}
std::cout<<std::endl;
}
cListSeq.Clear();
bEmpty = cTreeBinSeq.IsEmpty();
std::cout<<bEmpty<<std::endl;
dwDegree = cTreeBinSeq.GetDegree();
std::cout<<dwDegree<<std::endl;
dwHeight = cTreeBinSeq.GetHeight();
std::cout<<dwHeight<<std::endl;
dwNodesNum = cTreeBinSeq.GetNodesNum();
std::cout<<dwNodesNum<<std::endl; #endif
※数据结构※→☆非线性结构(tree)☆============二叉树 顺序存储结构(tree binary sequence)(十九)的更多相关文章
- C#数据结构-二叉树-顺序存储结构
什么是二叉树:每个树的节点只有两个子树的树形结构. 为什么使用顺序存储结构:使用数组存放满二叉树的各结点非常方便,可以根据一个结点的索引号很容易地推算出它的双亲.孩子.兄弟等结点的编号,从而对这些结点 ...
- 【Java】 大话数据结构(1) 线性表之顺序存储结构
本文根据<大话数据结构>一书,实现了Java版的顺序存储结构. 顺序存储结构指的是用一段地址连续的存储单元一次存储线性表的数据元素,一般用一维数组来实现. 书中的线性表抽象数据类型定义如 ...
- 数据结构线性表的动态分配顺序存储结构算法c语言具体实现和算法时间复杂度分析
#include<stdio.h>#include<stdlib.h>//线性表的动态分配顺序存储结构#define LIST_INIT_SIZE 100//线性表存储空间的初 ...
- c语言数据结构之线性表的顺序存储结构
线性表,即线性存储结构,将具有“一对一”关系的数据“线性”地存储到物理空间中,这种存储结构就称为线性存储结构,简称线性表. 注意:使用线性表存储的数据,要求数据类型必须一致,线性表存储的数据,要么全不 ...
- 数据结构之线性表的顺序存储结构的实现--C语言版
#include <stdio.h> #include <stdlib.h> #include <time.h> #define INIT_SIZE 100 #de ...
- [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)
循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...
- [置顶] ※数据结构※→☆线性表结构(queue)☆============队列 顺序存储结构(queue sequence)(八)
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除操作的 ...
- 数据结构4:顺序表(线性表的顺序存储结构)及C语言实现
逻辑结构上呈线性分布的数据元素在实际的物理存储结构中也同样相互之间紧挨着,这种存储结构称为线性表的顺序存储结构. 也就是说,逻辑上具有线性关系的数据按照前后的次序全部存储在一整块连续的内存空间中,之间 ...
- Leetcode 110 Balanced Binary Tree 二叉树
判断一棵树是否是平衡树,即左右子树的深度相差不超过1. 我们可以回顾下depth函数其实是Leetcode 104 Maximum Depth of Binary Tree 二叉树 /** * Def ...
随机推荐
- Hibernate(五)——面向对象查询语言和锁
Hibernate做了数据库中表和我们实体类的映射,使我们不必再编写sql语言了.但是有时候查询的特殊性,还是需要我们手动来写查询语句呢,Hibernate框架为了解决这个问题给我们提供了HQL(Hi ...
- PHP连接sql server 2005环境配置
一.Windows下PHP连接SQLServer 2005 设定:安装的Windows操作系统(Win7 或XP均可.其它系统暂未測试),在C盘下:PHP的相关文件位于c:/PHP以下,其配置文件ph ...
- 黑马程序猿 IO流 ByteArrayInputStream与ByteArrayOutputStream
---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- package cn.itcast.IO; i ...
- android自己定义ViewPager之——3D效果应用
今天在github里看到一个3D效果的ViewPager,感觉做出来的ViewPager滑动的时候效果十分的炫,就check out下来研究了一下怎样实现的.以及怎样使用.将整个ViewPager稍加 ...
- JAVA wait(), notify(),sleep具体解释
在CSDN开了博客后,一直也没在上面公布过文章,直到前一段时间与一位前辈的对话,才发现技术博客的重要,立志要把CSDN的博客建好.但一直没有找到好的开篇的主题,今天再看JAVA线程相互排斥.同步的时候 ...
- Leetcode 238 Product of Array Except Self 时间O(n)和空间O(1)解法
1. 问题描写叙述 给定一个n个整数的数组(n>1n>1)nums,返回一个数组output,当中的元素outputioutput_i的值为原数组nums中除numsinums_i之外的全 ...
- 观察者模式与Boost.Signals
1) 观察者模式定义 略,各种设计模式的书上都有定义. 2) 观察者模式一般实现 观察者模式一般实现,都是“被观察者”保存一个“观察者”的列表,循环这个列表来通知“观察者”.代码,其中使用了b ...
- Xcode5和6上新建工程如何本地化启动页面
建议阅读本篇文章前先具备iOS本地化的基本知识,Google中搜索“iOS本地化”,有成片的教程~~ 最近有个app需要支持英语.简体中文.繁体中文,由于启动页面上有文字,所以也不得不做下本地化处理. ...
- redhat换yum源
根据redhat操作系统版本及位数,下载对应centos的版本及位数的这些包: yum-3.2.22-40.el5.centos.noarch.rpm yum-fastestmirror-1.1.16 ...
- uva 230 Borrowers(摘)<vector>"结构体“ 膜拜!
I mean your borrowers of books--those mutilators of collections, spoilers of the symmetry of shelves ...