树(tree)
树(tree)是包含n(n>0)个结点的有穷集合,其中:
树也可以这样定义:树是由根结点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的结点,所定义的关系称为父子关系。父子关系在树的结点之间建立了一个层次结构。在这种层次结构中有一个结点具有特殊的地位,这个结点称为该树的根结点,或称为树根。
我们可以形式地给出树的递归定义如下:
树的四种遍历
1.先序遍历 (仅二叉树)
指先访问根,然后访问孩子的遍历方式
2.中序遍历(仅二叉树)
指先访问左(右)孩子,然后访问根,最后访问右(左)孩子的遍历方式
3.后序遍历(仅二叉树)
指先访问孩子,然后访问根的遍历方式
4.层次遍历
一层一层的访问,所以一般用广度优先遍历。
======================================================================================================
树结点 链式存储结构(tree node list)
结点:
包括一个数据元素及若干个指向其它子树的分支;例如,A,B,C,D等。在数据结构的图形表示中,对于数据集合中的每一个数据元素用中间标有元素值的方框表示,一般称之为数据结点,简称结点。
在C语言中,链表中每一个元素称为“结点”,每个结点都应包括两个部分:一为用户需要用的实际数据;二为下一个结点的地址,即指针域和数据域。
数据结构中的每一个数据结点对应于一个储存单元,这种储存单元称为储存结点,也可简称结点
树结点(树节点):
树节点相关术语:
根据树结点的相关定义,采用“双亲孩子表示法”。其属性如下:
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* m_pParent; //Parent position
AL_ListSeq*> 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++完整个代码示例(代码在VS2005下测试可运行)
AL_TreeNodeList.h
/**
@(#)$Id: AL_TreeNodeList.h 52 2013-09-23 10:38:22Z 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.
Chain storage structure//
The computer using a set of arbitrary linear table storage unit stores data elements (which may be a continuous plurality of memory
cells, it can be discontinuous).
It does not require the logic elements of adjacent physical location is adjacent to and therefore it is not sequential storage
structure has a weakness, but also lost the sequence table can be accessed randomly advantages.
Chain store structural features:
1, compared with sequential storage density storage structure (each node consists of data fields and pointers domains, so the same
space is full, then assume full order of more than chain stores).
2, the logic is not required on the adjacent node is physically adjacent.
3, insert, delete and flexible (not the mobile node, change the node as long as the pointer).
4, find the node when stored sequentially slower than the chain stores.
5, each node is a pointer to the data fields and domains.
@Author $Author: xiaoting $
@Date $Date: 2013-09-23 18:38:22 +0800 (周一, 23 九月 2013) $
@Revision $Revision: 52 $
@URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeList.h $
@Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeList.h 52 2013-09-23 10:38:22Z xiaoting $
*/
#ifndef CXX_AL_TREENODELIST_H
#define CXX_AL_TREENODELIST_H
#ifndef CXX_AL_LISTSINGLE_H
#include "AL_ListSingle.h"
#endif
#ifndef CXX_AL_QUEUELIST_H
#include "AL_QueueList.h"
#endif
///
// AL_TreeNodeList
///
template
class AL_TreeNodeList
{
public:
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
~AL_TreeNodeList();
/**
* 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
* @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
* @return
* @note
* @attention
*/
VOID SetData(const T& tTemplate);
/**
* GetParent
*
* @param
* @return AL_TreeNodeList*
* @note parent node pointer, not to manager memory
* @attention
*/
AL_TreeNodeList* GetParent() const;
/**
* SetParent
*
* @param DWORD dwIndex
* @param AL_TreeNodeList* pParent
* @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 )
*/
BOOL SetParent(DWORD dwIndex, AL_TreeNodeList* pParent);
/**
* SetParentLeft
*
* @param AL_TreeNodeList* pParent
* @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_TreeNodeList* pParent);
/**
* SetParentRight
*
* @param AL_TreeNodeList* pParent
* @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_TreeNodeList* pParent);
/**
* Insert
*
* @param DWORD dwIndex
* @param AL_TreeNodeList* pInsertChild
* @return BOOL
* @note inset the const AL_TreeNodeList* into the child notes at the position
* @attention
*/
BOOL Insert(DWORD dwIndex, AL_TreeNodeList* pInsertChild);
/**
* InsertLeft
*
* @param AL_TreeNodeList* pInsertChild
* @return BOOL
* @note inset the const AL_TreeNodeList* into the child notes at the left
* @attention
*/
BOOL InsertLeft(AL_TreeNodeList* pInsertChild);
/**
* InsertRight
*
* @param AL_TreeNodeList* pInsertChild
* @return BOOL
* @note inset the const AL_TreeNodeList* into the child notes at the right
* @attention
*/
BOOL InsertRight(AL_TreeNodeList* pInsertChild);
/**
* GetChild
*
* @param DWORD dwIndex
* @return AL_TreeNodeList*
* @note the dwIndex must is little than the node degree
* @attention
*/
AL_TreeNodeList* GetChild(DWORD dwIndex) const;
/**
* GetChildLeft
*
* @param
* @return AL_TreeNodeList*
* @note
* @attention
*/
AL_TreeNodeList* GetChildLeft() const;
/**
* GetChildRight
*
* @param
* @return AL_TreeNodeList*
* @note
* @attention
*/
AL_TreeNodeList* 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_TreeNodeList* pChild
* @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_TreeNodeList* pChild) const;
/**
* GetSibling
*
* @param AL_ListSingle*>& listSibling
* @return BOOL
* @note sibling nodes: nodes with the same parent node is called mutual sibling;
* @attention
*/
BOOL GetSibling(AL_ListSingle*>& listSibling) const;
/**
* GetAncestor
*
* @param AL_ListSingle*>& listAncestor
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention
*/
BOOL GetAncestor(AL_ListSingle*>& listAncestor) const;
/**
* GetDescendant
*
* @param AL_ListSingle*>& listDescendant
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention
*/
BOOL GetDescendant(AL_ListSingle*>& listDescendant) const;
protected:
public:
/**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
AL_TreeNodeList();
/**
* Construction
*
* @param const T& tTemplate
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
AL_TreeNodeList(const T& tTemplate);
/**
*Copy Construct
*
* @param const AL_TreeNodeList& cAL_TreeNodeList
* @return
*/
AL_TreeNodeList(const AL_TreeNodeList& cAL_TreeNodeList);
/**
*Assignment
*
* @param const AL_TreeNodeList& cAL_TreeNodeList
* @return AL_TreeNodeList&
*/
AL_TreeNodeList& operator = (const AL_TreeNodeList& cAL_TreeNodeList);
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_TreeNodeList* m_pParent; //Parent tree node
AL_ListSingle*> m_listChild; //All Child tree node
};
///
// AL_TreeNodeList
///
/**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
template
AL_TreeNodeList::AL_TreeNodeList():
m_dwLevel(0x00),
m_pParent(NULL)
{
//memset(&m_data, 0x00, sizeof(T)); //can not use memset, as to pointer or virtural pointer of class
m_listChild.Clear();
}
/**
* Construction
*
* @param const T& tTemplate
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
template
AL_TreeNodeList::AL_TreeNodeList(const T& tTemplate):
m_dwLevel(0x00),
m_data(tTemplate),
m_pParent(NULL)
{
m_listChild.Clear();
}
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
template
AL_TreeNodeList::~AL_TreeNodeList()
{
//it doesn't matter to clear the pointer or not.
m_dwLevel = 0x00;
m_pParent = NULL; //not to manager the memory
m_listChild.Clear();
}
/**
* 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 DWORD
AL_TreeNodeList::GetLevel() const
{
return m_dwLevel;
}
/**
* SetLevel
*
* @param DWORD dwLevel
* @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 VOID
AL_TreeNodeList::SetLevel(DWORD dwLevel)
{
m_dwLevel = dwLevel;
}
/**
* GetData
*
* @param
* @return T
* @note
* @attention
*/
template T
AL_TreeNodeList::GetData() const
{
return m_data;
}
/**
* SetData
*
* @param const T& tTemplate
* @return
* @note
* @attention
*/
template VOID
AL_TreeNodeList::SetData(const T& tTemplate)
{
m_data = tTemplate;
}
/**
* GetParent
*
* @param
* @return AL_TreeNodeList*
* @note parent node pointer, not to manager memory
* @attention
*/
template AL_TreeNodeList*
AL_TreeNodeList::GetParent() const
{
return m_pParent;
}
/**
* SetParent
*
* @param DWORD dwIndex
* @param AL_TreeNodeList* pParent
* @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 )
*/
template BOOL
AL_TreeNodeList::SetParent(DWORD dwIndex, AL_TreeNodeList* pParent)
{
BOOL bSetParent = FALSE;
bSetParent = pParent->Insert(dwIndex, this);
if (TRUE == bSetParent) {
//current node insert to the parent successfully
m_pParent = pParent;
}
return bSetParent;
}
/**
* SetParentLeft
*
* @param AL_TreeNodeList* pParent
* @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 BOOL
AL_TreeNodeList::SetParentLeft(AL_TreeNodeList* pParent)
{
return SetParent(0x00, pParent);
}
/**
* SetParentRight
*
* @param AL_TreeNodeList* pParent
* @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 BOOL
AL_TreeNodeList::SetParentRight(AL_TreeNodeList* pParent)
{
return SetParent(pParent->GetDegree(), pParent);
}
/**
* Insert
*
* @param DWORD dwIndex
* @param AL_TreeNodeList* pInsertChild
* @return BOOL
* @note inset the const AL_TreeNodeList* into the child notes at the position
* @attention
*/
template BOOL
AL_TreeNodeList::Insert(DWORD dwIndex, AL_TreeNodeList* pInsertChild)
{
BOOL bInsert = FALSE;
bInsert = m_listChild.Insert(dwIndex, pInsertChild);
if (TRUE == bInsert) {
if (GetLevel()+1 != pInsertChild->GetLevel()) {
//deal with the child level
INT iLevelDiff = pInsertChild->GetLevel() - GetLevel();
pInsertChild->SetLevel(GetLevel()+1);
AL_ListSingle*> listDescendant;
if (FALSE == GetDescendant(listDescendant)) {
return FALSE;
}
AL_TreeNodeList* pDescendant = NULL;
for (DWORD dwCnt=0; dwCntSetLevel(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_TreeNodeList* pInsertChild
* @return BOOL
* @note inset the const AL_TreeNodeList* into the child notes at the left
* @attention
*/
template BOOL
AL_TreeNodeList::InsertLeft(AL_TreeNodeList* pInsertChild)
{
return Insert(0x00, pInsertChild);
}
/**
* InsertRight
*
* @param AL_TreeNodeList* pInsertChild
* @return BOOL
* @note inset the const AL_TreeNodeList* into the child notes at the right
* @attention
*/
template BOOL
AL_TreeNodeList::InsertRight(AL_TreeNodeList* pInsertChild)
{
return Insert(GetDegree(), pInsertChild);
}
/**
* GetChild
*
* @param DWORD dwIndex
* @return AL_TreeNodeList*
* @note the dwIndex must is little than the node degree
* @attention
*/
template AL_TreeNodeList*
AL_TreeNodeList::GetChild(DWORD dwIndex) const
{
AL_TreeNodeList* pChild = NULL;
if (TRUE == m_listChild.Get(pChild, dwIndex)) {
return pChild;
}
return NULL;
}
/**
* GetChildLeft
*
* @param
* @return AL_TreeNodeList*
* @note
* @attention
*/
template AL_TreeNodeList*
AL_TreeNodeList::GetChildLeft() const
{
return GetChild(0x00);
}
/**
* GetChildRight
*
* @param
* @return AL_TreeNodeList*
* @note
* @attention
*/
template AL_TreeNodeList*
AL_TreeNodeList::GetChildRight() const
{
return GetChild(GetDegree());
}
/**
* GetDegree
*
* @param
* @return DWORD
* @note degree node: A node of the subtree containing the number is called the node degree;
* @attention
*/
template DWORD
AL_TreeNodeList::GetDegree() const
{
return m_listChild.Length();
}
/**
* IsLeaf
*
* @param
* @return BOOL
* @note leaf nodes or terminal nodes: degree 0 are called leaf nodes;
* @attention
*/
template BOOL
AL_TreeNodeList::IsLeaf() const
{
// return (TRUE == m_listChild.IsEmpty()) ? TRUE:FALSE;
return (0x00 == GetDegree()) ? TRUE:FALSE;
}
/**
* IsBranch
*
* @param
* @return BOOL
* @note non-terminal node or branch node: node degree is not 0;
* @attention
*/
template BOOL
AL_TreeNodeList::IsBranch() const
{
// return (FALSE == m_listChild.IsEmpty()) ? TRUE:FALSE;
return (0x00 != GetDegree()) ? TRUE:FALSE;
}
/**
* IsParent
*
* @param const AL_TreeNodeList* pChild
* @return BOOL
* @note parent node or the parent node: If a node contains a child node, this node is called its child
* @attention
*/
template BOOL
AL_TreeNodeList::IsParent(const AL_TreeNodeList* pChild) const
{
// AL_TreeNodeList* pCompare = NULL;
// for (DWORD dwCnt=0; dwCntm_pParent) {
return TRUE;
}
return FALSE;
}
/**
* GetSibling
*
* @param AL_ListSingle*>& listSibling
* @return BOOL
* @note sibling nodes: nodes with the same parent node is called mutual sibling;
* @attention
*/
template BOOL
AL_TreeNodeList::GetSibling(AL_ListSingle*>& listSibling) const
{
BOOL bSibling = FALSE;
if (NULL == m_pParent) {
//not parent node
return bSibling;
}
AL_ListSingle*>& listParentChild = m_pParent->m_listChild;
AL_TreeNodeList* pParentChild = NULL;
for (DWORD dwCnt=0; dwCntGetDegree(); dwCnt++) {
pParentChild = m_pParent->GetChild(dwCnt);
if (NULL != pParentChild) {
//get the child
if (pParentChild == this) {
//itself
continue;
}
listSibling.InsertEnd(pParentChild);
bSibling = TRUE;
}
else {
//error can not get the child
return FALSE;
}
}
return bSibling;
}
/**
* GetAncestor
*
* @param AL_ListSingle*>& listAncestor
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention
*/
template BOOL
AL_TreeNodeList::GetAncestor(AL_ListSingle*>& listAncestor) const
{
if (NULL == m_pParent) {
//not parent node
return FALSE;
}
AL_TreeNodeList* pParent = m_pParent;
while (NULL != pParent) {
listAncestor.InsertEnd(pParent);
pParent = pParent->m_pParent;
}
return TRUE;
}
/**
* GetDescendant
*
* @param AL_ListSingle*>& listDescendant
* @return BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention
*/
template BOOL
AL_TreeNodeList::GetDescendant(AL_ListSingle*>& listDescendant) const
{
if (TRUE == IsLeaf()) {
//child node
return FALSE;
}
AL_TreeNodeList* pDescendant = NULL;
for (DWORD dwCnt=0; dwCnt* pDescendantLoop = NULL;
while (TRUE == listDescendant.Get(pDescendant, dwDescendantLoop)) {
dwDescendantLoop++;
if (NULL != pDescendant) {
for (DWORD dwCnt=0; dwCntGetDegree(); dwCnt++) {
pDescendantLoop = pDescendant->GetChild(dwCnt);
if (NULL != pDescendantLoop) {
//get the descendant
listDescendant.InsertEnd(pDescendantLoop);
}
else {
//error can not get the descendant
return FALSE;
}
}
}
else {
//error
return FALSE;
}
}
return TRUE;
/*
AL_TreeNodeList* pDescendant = NULL;
AL_QueueList*> queueDescendant;
for (DWORD dwCnt=0; dwCnt* pDescendantLoop = NULL;
AL_TreeNodeList* pDescendantChild = NULL;
while (FALSE == queueDescendant.IsEmpty()) {
if (TRUE == queueDescendant.Pop(pDescendantLoop)) {
if (NULL != pDescendantLoop) {
listDescendant.InsertEnd(pDescendantLoop);
for (DWORD dwCnt=0; dwCntGetDegree(); dwCnt++) {
pDescendantChild = pDescendantLoop->GetChild(dwCnt);
if (NULL != pDescendantChild) {
queueDescendant.Push(pDescendantChild);
}
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
}
return TRUE;
*/
}
/**
*Assignment
*
* @param const AL_TreeNodeList& cAL_TreeNodeList
* @return AL_TreeNodeList&
*/
template AL_TreeNodeList&
AL_TreeNodeList::operator = (const AL_TreeNodeList& cAL_TreeNodeList)
{
m_dwLevel = cAL_TreeNodeList.m_dwLevel;
m_data = cAL_TreeNodeList.m_data;
m_pParent = cAL_TreeNodeList.m_pParent;
m_listChild = cAL_TreeNodeList.m_listChild;
return *this;
}
#endif // CXX_AL_TREENODELIST_H
/* EOF */
/**
@(#)$Id: AL_TreeList.h 54 2013-09-24 05:59:38Z 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.
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 13:59:38 +0800 (周二, 24 九月 2013) $
@Revision $Revision: 54 $
@URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeList.h $
@Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeList.h 54 2013-09-24 05:59:38Z xiaoting $
*/
#ifndef CXX_AL_TREELIST_H
#define CXX_AL_TREELIST_H
#ifndef CXX_AL_LISTSINGLE_H
#include "AL_ListSingle.h"
#endif
#ifndef CXX_AL_QUEUELIST_H
#include "AL_QueueList.h"
#endif
///
// AL_TreeList
///
template
class AL_TreeList
{
public:
/**
* Construction
*
* @param DWORD dwSize (default value: TREESEQ_DEFAULTSIZE)
* @return
* @note
* @attention
*/
AL_TreeList();
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
~AL_TreeList();
/**
* IsEmpty
*
* @param VOID
* @return BOOL
* @note the tree has data?
* @attention
*/
BOOL IsEmpty() const;
/**
* GetRootNode
*
* @param
* @return const AL_TreeNodeList*
* @note Get the root data
* @attention
*/
const AL_TreeNodeList* 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();
/**
* LevelOrderTraversal
*
* @param AL_ListSingle& listOrder
* @return BOOL
* @note Level-order traversal
* @attention
*/
BOOL LevelOrderTraversal(AL_ListSingle& listOrder) const;
/**
* GetSiblingAtNode
*
* @param AL_ListSingle& listSibling
* @param const AL_TreeNodeList* pCurTreeNode
* @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_ListSingle& listSibling, const AL_TreeNodeList* pCurTreeNode) const;
/**
* GetAncestorAtNode
*
* @param AL_ListSingle& listAncestor
* @param const AL_TreeNodeList* pCurTreeNode
* @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_ListSingle& listAncestor, const AL_TreeNodeList* pCurTreeNode) const;
/**
* GetDescendantAtNode
*
* @param AL_ListSingle& listDescendant
* @param const AL_TreeNodeList* pCurTreeNode
* @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_ListSingle& listDescendant, const AL_TreeNodeList* pCurTreeNode) const;
/**
* InsertRoot
*
* @param const T& tTemplate
* @return BOOL
* @note
* @attention
*/
BOOL InsertRoot(const T& tTemplate);
/**
* InsertAtNode
*
* @param AL_TreeNodeList* pCurTreeNode
* @param DWORD dwIndex
* @param const T& tTemplate
* @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_TreeNodeList* pCurTreeNode, DWORD dwIndex, const T& tTemplate);
/**
* InsertLeftAtNode
*
* @param AL_TreeNodeList* pCurTreeNode
* @param const T& tTemplate
* @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_TreeNodeList* pCurTreeNode, const T& tTemplate);
/**
* InsertRightAtNode
*
* @param AL_TreeNodeList* pCurTreeNode
* @param const T& tTemplate
* @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_TreeNodeList* pCurTreeNode, const T& tTemplate);
/**
* GetChildNodeAtNode
*
* @param const AL_TreeNodeList* pCurTreeNode
* @param DWORD dwIndex
* @return const AL_TreeNodeList*
* @note get the current tree node (pCurTreeNode)'s child node at the position (dwIndex)
* @attention the current tree node must be in the tree
*/
const AL_TreeNodeList* GetChildNodeAtNode(const AL_TreeNodeList* pCurTreeNode, DWORD dwIndex) const;
/**
* GetChildNodeLeftAtNode
*
* @param const AL_TreeNodeList* pCurTreeNode
* @return const AL_TreeNodeList*
* @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_TreeNodeList* GetChildNodeLeftAtNode(const AL_TreeNodeList* pCurTreeNode) const;
/**
* GetChildNodeRightAtNode
*
* @param const AL_TreeNodeList* pCurTreeNode
* @return const AL_TreeNodeList*
* @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_TreeNodeList* GetChildNodeRightAtNode(const AL_TreeNodeList* pCurTreeNode) const;
protected:
private:
/**
*Copy Construct
*
* @param const AL_TreeList& cAL_TreeList
* @return
*/
AL_TreeList(const AL_TreeList& cAL_TreeList);
/**
*Assignment
*
* @param const AL_TreeList& cAL_TreeList
* @return AL_TreeList&
*/
AL_TreeList& operator = (const AL_TreeList& cAL_TreeList);
public:
protected:
private:
DWORD m_dwDegree;
DWORD m_dwHeight;
DWORD m_NumNodes;
AL_TreeNodeList* m_pRootNode;
};
///
// AL_TreeList
///
/**
* Construction
*
* @param
* @return
* @note
* @attention
*/
template
AL_TreeList::AL_TreeList():
m_dwDegree(0xffffffff),
m_dwHeight(0x00),
m_NumNodes(0x00),
m_pRootNode(NULL)
{
}
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
template
AL_TreeList::~AL_TreeList()
{
Clear();
}
/**
* IsEmpty
*
* @param VOID
* @return BOOL
* @note the tree has data?
* @attention
*/
template BOOL
AL_TreeList::IsEmpty() const
{
return (0x00 == m_NumNodes) ? TRUE:FALSE;
}
/**
* GetRootNode
*
* @param
* @return const AL_TreeNodeList*
* @note Get the root data
* @attention
*/
template const AL_TreeNodeList*
AL_TreeList::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 DWORD
AL_TreeList::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 DWORD
AL_TreeList::GetHeight() const
{
return m_dwHeight;
}
/**
* GetNodesNum
*
* @param
* @return DWORD
* @note get the notes number of the tree
* @attention
*/
template DWORD
AL_TreeList::GetNodesNum() const
{
return m_NumNodes;
}
/**
* Clear
*
* @param
* @return
* @note
* @attention
*/
template VOID
AL_TreeList::Clear()
{
m_dwDegree = 0xffffffff;
m_dwHeight = 0x00;
m_NumNodes = 0x00;
AL_ListSingle*> listDescendant;
if (NULL != m_pRootNode) {
if (TRUE == m_pRootNode->GetDescendant(listDescendant)) {
AL_TreeNodeList* pDescendant;
for (DWORD dwDelete=0; dwDelete& listOrder
* @return BOOL
* @note Level-order traversal
* @attention
*/
template BOOL
AL_TreeList::LevelOrderTraversal(AL_ListSingle& listOrder) const
{
if (TRUE == IsEmpty()) {
return FALSE;
}
if (NULL == m_pRootNode) {
return FALSE;
}
listOrder.Clear();
/*
AL_ListSingle*> listNodeOrder;
listNodeOrder.InsertEnd(m_pRootNode);
//loop the all node
DWORD dwNodeOrderLoop = 0x00;
AL_TreeNodeList* pNodeOrderLoop = NULL;
AL_TreeNodeList* pNodeOrderChild = NULL;
while (TRUE == listNodeOrder.Get(pNodeOrderLoop, dwNodeOrderLoop)) {
dwNodeOrderLoop++;
if (NULL != pNodeOrderLoop) {
listOrder.InsertEnd(pNodeOrderLoop->GetData());
for (DWORD dwCnt=0; dwCntGetDegree(); dwCnt++) {
pNodeOrderChild = pNodeOrderLoop->GetChild(dwCnt);
if (NULL != pNodeOrderChild) {
//get the descendant
listNodeOrder.InsertEnd(pNodeOrderChild);
}
else {
//error can not get the descendant
return FALSE;
}
}
}
else {
//error
return FALSE;
}
}
return TRUE;
*/
AL_QueueList*> queueOrder;
queueOrder.Push(m_pRootNode);
AL_TreeNodeList* pNodeOrderLoop = NULL;
AL_TreeNodeList* pNodeOrderChild = NULL;
while (FALSE == queueOrder.IsEmpty()) {
if (TRUE == queueOrder.Pop(pNodeOrderLoop)) {
if (NULL != pNodeOrderLoop) {
listOrder.InsertEnd(pNodeOrderLoop->GetData());
for (DWORD dwCnt=0; dwCntGetDegree(); dwCnt++) {
pNodeOrderChild = pNodeOrderLoop->GetChild(dwCnt);
if (NULL != pNodeOrderChild) {
queueOrder.Push(pNodeOrderChild);
}
}
}
else {
return FALSE;
}
}
else {
return FALSE;
}
}
return TRUE;
}
/**
* GetSiblingAtNode
*
* @param AL_ListSingle& listSibling
* @param const AL_TreeNodeList* pCurTreeNode
* @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 BOOL
AL_TreeList::GetSiblingAtNode(AL_ListSingle& listSibling, const AL_TreeNodeList* pCurTreeNode) const
{
if (NULL == pCurTreeNode) {
return FALSE;
}
AL_ListSingle*> listTreeNodeSibling;
if (FALSE == pCurTreeNode->GetSibling(listTreeNodeSibling)) {
return FALSE;
}
//clear listSibling
listSibling.Clear();
AL_TreeNodeList* pTreeNodeSibling = NULL;
for (DWORD dwCnt=0; dwCntGetData());
}
else {
//error
return FALSE;
}
}
else {
//error
return FALSE;
}
}
return TRUE;
}
/**
* GetAncestorAtNode
*
* @param AL_ListSingle& listAncestor
* @param const AL_TreeNodeList* pCurTreeNode
* @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 BOOL
AL_TreeList::GetAncestorAtNode(AL_ListSingle& listAncestor, const AL_TreeNodeList* pCurTreeNode) const
{
if (NULL == pCurTreeNode) {
return FALSE;
}
AL_ListSingle*> listTreeNodeAncestor;
if (FALSE == pCurTreeNode->GetAncestor(listTreeNodeAncestor)) {
return FALSE;
}
//clear listAncestor
listAncestor.Clear();
AL_TreeNodeList* pTreeNodeAncestor = NULL;
for (DWORD dwCnt=0; dwCntGetData());
}
else {
//error
return FALSE;
}
}
else {
//error
return FALSE;
}
}
return TRUE;
}
/**
* GetDescendantAtNode
*
* @param AL_ListSingle& listDescendant
* @param const AL_TreeNodeList* pCurTreeNode
* @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 BOOL
AL_TreeList::GetDescendantAtNode(AL_ListSingle& listDescendant, const AL_TreeNodeList* pCurTreeNode) const
{
if (NULL == pCurTreeNode) {
return FALSE;
}
AL_ListSingle*> listTreeNodeDescendant;
if (FALSE == pCurTreeNode->GetDescendant(listTreeNodeDescendant)) {
return FALSE;
}
//clear listAncestor
listDescendant.Clear();
AL_TreeNodeList* pTreeNodeDescendant = NULL;
for (DWORD dwCnt=0; dwCntGetData());
}
else {
//error
return FALSE;
}
}
else {
//error
return FALSE;
}
}
return TRUE;
}
/**
* InsertRoot
*
* @param const T& tTemplate
* @return BOOL
* @note
* @attention
*/
template BOOL
AL_TreeList::InsertRoot(const T& tTemplate)
{
return InsertAtNode(NULL, 0x00, tTemplate);
}
/**
* InsertAtNode
*
* @param AL_TreeNodeList* pCurTreeNode
* @param DWORD dwIndex
* @param const T& tTemplate
* @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 BOOL
AL_TreeList::InsertAtNode(AL_TreeNodeList* pCurTreeNode, DWORD dwIndex, const T& tTemplate)
{
AL_TreeNodeList* pTreeNode = NULL;
if (TRUE == IsEmpty()) {
if (NULL != pCurTreeNode) {
//error can not insert to the current node pCurTreeNode, is not exist in the tree
return FALSE;
}
else {
pTreeNode = new AL_TreeNodeList;
if (NULL == pTreeNode) {
return FALSE;
}
pTreeNode->SetData(tTemplate);
pTreeNode->SetLevel(0x00);
m_pRootNode = pTreeNode;
m_dwDegree = 0x00;
m_dwHeight = 0x00; //empty tree 0xffffffff (-1)
m_NumNodes++;
return TRUE;
}
}
if (NULL == pCurTreeNode) {
return FALSE;
}
//inset to the current tree node
pTreeNode = new AL_TreeNodeList;
if (NULL == pTreeNode) {
return FALSE;
}
pTreeNode->SetData(tTemplate);
pTreeNode->SetLevel(pCurTreeNode->GetLevel() + 1);
if (FALSE == pCurTreeNode->Insert(dwIndex, pTreeNode)) {
delete pTreeNode;
pTreeNode = NULL;
return FALSE;
}
DWORD dwCurNodeDegree = 0x00;
//loop all node to get the current node degree
if (pCurTreeNode->GetDegree() > m_dwDegree) {
m_dwDegree = pCurTreeNode->GetDegree();
}
if (pTreeNode->GetLevel() > m_dwHeight) {
m_dwHeight =pTreeNode->GetLevel();
}
m_NumNodes++;
return TRUE;
}
/**
* InsertLeftAtNode
*
* @param AL_TreeNodeList* pCurTreeNode
* @param const T& tTemplate
* @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 BOOL
AL_TreeList::InsertLeftAtNode(AL_TreeNodeList* pCurTreeNode, const T& tTemplate)
{
return InsertAtNode(pCurTreeNode, 0x00, tTemplate);
}
/**
* InsertRightAtNode
*
* @param AL_TreeNodeList* pCurTreeNode
* @param const T& tTemplate
* @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 BOOL
AL_TreeList::InsertRightAtNode(AL_TreeNodeList* pCurTreeNode, const T& tTemplate)
{
return InsertAtNode(pCurTreeNode, pCurTreeNode->GetDegree(), tTemplate);
}
/**
* GetChildNodeAtNode
*
* @param const AL_TreeNodeList* pCurTreeNode
* @param DWORD dwIndex
* @return const AL_TreeNodeList*
* @note get the current tree node (pCurTreeNode)'s child node at the position (dwIndex)
* @attention the current tree node must be in the tree
*/
template const AL_TreeNodeList*
AL_TreeList::GetChildNodeAtNode(const AL_TreeNodeList* pCurTreeNode, DWORD dwIndex) const
{
if (NULL == pCurTreeNode) {
return NULL;
}
return pCurTreeNode->GetChild(dwIndex);
}
/**
* GetChildNodeLeftAtNode
*
* @param const AL_TreeNodeList* pCurTreeNode
* @return const AL_TreeNodeList*
* @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 const AL_TreeNodeList*
AL_TreeList::GetChildNodeLeftAtNode(const AL_TreeNodeList* pCurTreeNode) const
{
return GetChildNodeAtNode(pCurTreeNode, 0x00);
}
/**
* GetChildNodeRightAtNode
*
* @param const AL_TreeNodeList* pCurTreeNode
* @return const AL_TreeNodeList*
* @note get the current tree node (pCurTreeNode)'s child node at the position (right)
* @attention
*/
template const AL_TreeNodeList*
AL_TreeList::GetChildNodeRightAtNode(const AL_TreeNodeList* pCurTreeNode) const
{
return GetChildNodeAtNode(pCurTreeNode, pCurTreeNode->GetDegree());
}
#endif // CXX_AL_TREELIST_H
/* EOF */
测试代码
#ifdef TEST_AL_TREELIST
AL_TreeList cTreeList;
BOOL bEmpty = cTreeList.IsEmpty();
std::cout<* pConstRootNode = cTreeList.GetRootNode();
AL_TreeNodeList* pRootNode = const_cast*>(pConstRootNode);
std::cout<*>(pConstRootNode);
std::cout<* pConstTreeNode = cTreeList.GetChildNodeAtNode(pRootNode, 0x00);
AL_TreeNodeList* pTreeNode = const_cast*>(pConstTreeNode);
std::cout<* pConstTreeNode20 = cTreeList.GetChildNodeAtNode(pTreeNode, 0x00);
AL_TreeNodeList* pTreeNode20 = const_cast*>(pConstTreeNode20);
std::cout<* pConstTreeNode33 = cTreeList.GetChildNodeAtNode(pTreeNode20, 0x3);
AL_TreeNodeList* pTreeNode33 = const_cast*>(pConstTreeNode33);
if (NULL != pTreeNode) {
std::cout<GetLevel()<<" "<GetData()<<" "<GetDegree()<IsLeaf()<<" "<IsBranch()<<" "<IsParent(pTreeNode)<<" "<IsParent(pTreeNode33)<GetLevel()<<" "<GetData()<<" "<GetDegree()<IsLeaf()<<" "<IsBranch()<<" "<IsParent(pTreeNode)<<" "<IsParent(pTreeNode33)<GetLevel()<<" "<GetData()<<" "<GetDegree()<IsLeaf()<<" "<IsBranch()<<" "<IsParent(pTreeNode)<<" "<IsParent(pTreeNode33)<* pChild = NULL;
pChild = cTreeList.GetChildNodeAtNode(pTreeNode, 0x01);
if (NULL != pChild) {
std::cout<GetLevel()<<" "<GetData()<<" "<GetDegree()<IsLeaf()<<" "<IsBranch()<<" "<IsParent(pTreeNode)<<" "<IsParent(pTreeNode33)<GetLevel()<<" "<GetData()<<" "<GetDegree()<IsLeaf()<<" "<IsBranch()<<" "<IsParent(pTreeNode)<<" "<IsParent(pTreeNode33)<GetLevel()<<" "<GetData()<<" "<GetDegree()<IsLeaf()<<" "<IsBranch()<<" "<IsParent(pTreeNode)<<" "<IsParent(pTreeNode33)<GetLevel()<<" "<GetData()<<" "<GetDegree()<IsLeaf()<<" "<IsBranch()<<" "<IsParent(pTreeNode)<<" "<IsParent(pTreeNode33)<GetLevel()<<" "<GetData()<<" "<GetDegree()<IsLeaf()<<" "<IsBranch()<<" "<IsParent(pTreeNode)<<" "<IsParent(pTreeNode33)< cListSingle;
DWORD dwData;
BOOL bSibling = cTreeList.GetSiblingAtNode(cListSingle, pTreeNode);
if (TRUE == bSibling) {
for (DWORD dwCnt=0; dwCnt