※数据结构※→☆非线性结构(tree)☆============树 顺序存储结构(tree sequence)(十五)

树(tree)

        树(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_TreeNodeSeq.h

/**
  @(#)$Id: AL_TreeNodeSeq.h 48 2013-09-23 05:48:41Z 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.

  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-23 13:48:41 +0800 (周一, 23 九月 2013) $
  @Revision $Revision: 48 $
  @URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeSeq.h $
  @Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeSeq.h 48 2013-09-23 05:48:41Z xiaoting $
 */

#ifndef CXX_AL_TREENODESEQ_H
#define CXX_AL_TREENODESEQ_H

#ifndef CXX_AL_LISTSEQ_H
#include "AL_ListSeq.h"
#endif

///
//			AL_TreeNodeSeq
///

template<typename T> class AL_TreeSeq;

template<typename T> 
class AL_TreeNodeSeq
{
public:
	/**
	* Destruction
	*
	* @param
	* @return
	* @note
	* @attention 
	*/
	~AL_TreeNodeSeq();
	
	/**
	* 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_TreeNodeSeq<T>*	
	* @note parent node pointer, not to manager memory
	* @attention 
	*/
	AL_TreeNodeSeq<T>*	GetParent() const;

	/**
	* SetParent
	*
	* @param	DWORD dwIndex <IN>
	* @param	AL_TreeNodeSeq<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 )
	*/
	BOOL SetParent(DWORD dwIndex, AL_TreeNodeSeq<T>* pParent);

	/**
	* SetParentLeft
	*
	* @param	AL_TreeNodeSeq<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_TreeNodeSeq<T>* pParent);

	/**
	* SetParentRight
	*
	* @param	AL_TreeNodeSeq<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_TreeNodeSeq<T>* pParent);

	/**
	* Insert
	*
	* @param	DWORD dwIndex <IN>
	* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the position
	* @attention
	*/
	BOOL Insert(DWORD dwIndex, AL_TreeNodeSeq<T>* pInsertChild);

	/**
	* InsertLeft
	*
	* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the left
	* @attention
	*/
	BOOL InsertLeft(AL_TreeNodeSeq<T>* pInsertChild);

	/**
	* InsertRight
	*
	* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the right
	* @attention
	*/
	BOOL InsertRight(AL_TreeNodeSeq<T>* pInsertChild);

	/**
	* GetChild
	*
	* @param	DWORD dwIndex <IN>
	* @return	AL_TreeNodeSeq<T>*
	* @note the dwIndex must is little than the node degree
	* @attention
	*/
	AL_TreeNodeSeq<T>* GetChild(DWORD dwIndex) const;

	/**
	* GetChildLeft
	*
	* @param	
	* @return	AL_TreeNodeSeq<T>*
	* @note 
	* @attention
	*/
	AL_TreeNodeSeq<T>* GetChildLeft() const;

	/**
	* GetChildRight
	*
	* @param	
	* @return	AL_TreeNodeSeq<T>*
	* @note 
	* @attention
	*/
	AL_TreeNodeSeq<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_TreeNodeSeq<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_TreeNodeSeq<T>* pChild) const;

	/**
	* GetSibling
	*
	* @param	AL_ListSeq<AL_TreeNodeSeq<T>*>& listSibling <OUT>
	* @return	BOOL
	* @note sibling nodes: nodes with the same parent node is called mutual sibling;
	* @attention 
	*/
	BOOL GetSibling(AL_ListSeq<AL_TreeNodeSeq<T>*>& listSibling) const;

	/**
	* GetAncestor
	*
	* @param	AL_ListSeq<AL_TreeNodeSeq<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_TreeNodeSeq<T>*>& listAncestor) const;

	/**
	* GetDescendant
	*
	* @param	AL_ListSeq<AL_TreeNodeSeq<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_TreeNodeSeq<T>*>& listDescendant) const;

protected:
private:
	friend class AL_TreeSeq<T>;

	/**
	* Construction
	*
	* @param
	* @return
	* @note private the Construction, avoid the others use it
	* @attention
	*/
	AL_TreeNodeSeq();
	
	/**
	* Construction
	*
	* @param	const T& tTemplate <IN>
	* @return
	* @note
	* @attention private the Construction, avoid the others use it
	*/
	AL_TreeNodeSeq(const T& tTemplate);

	/**
	*Copy Construct
	*
	* @param	const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq
	* @return
	*/
	AL_TreeNodeSeq(const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq);

	/**
	*Assignment
	*
	* @param	const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq
	* @return	AL_TreeNodeSeq<T>&
	*/
	AL_TreeNodeSeq<T>& operator = (const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq);

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_TreeNodeSeq<T>*					m_pParent;				//Parent position
	AL_ListSeq<AL_TreeNodeSeq<T>*>		m_listChild;			//All Child tree node
};

///
//			AL_TreeNodeSeq
///

/**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
template<typename T>
AL_TreeNodeSeq<T>::AL_TreeNodeSeq():
m_dwLevel(0x00),
m_pParent(NULL)
{
	m_listChild.Clear();
}

/**
* Construction
*
* @param	const T& tTemplate <IN>
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
template<typename T>
AL_TreeNodeSeq<T>::AL_TreeNodeSeq(const T& tTemplate):
m_dwLevel(0x00),
m_data(tTemplate),
m_pParent(NULL)
{
	m_listChild.Clear();
}


/**
* Destruction
*
* @param
* @return
* @note
* @attention 
*/
template<typename T>
AL_TreeNodeSeq<T>::~AL_TreeNodeSeq()
{
	//it doesn't matter to clear the pointer or not.
	m_dwLevel = 0x00;
	m_pParent = NULL;
	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<typename T> DWORD 
AL_TreeNodeSeq<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_TreeNodeSeq<T>::SetLevel(DWORD dwLevel)
{
	m_dwLevel = dwLevel;
}

/**
* GetData
*
* @param
* @return	T
* @note 
* @attention 
*/
template<typename T> T 
AL_TreeNodeSeq<T>::GetData() const
{
	return m_data;
}

/**
* SetData
*
* @param	const T& tTemplate <IN>
* @return	
* @note 
* @attention 
*/
template<typename T> VOID 
AL_TreeNodeSeq<T>::SetData(const T& tTemplate)
{
	m_data = tTemplate;
}

/**
* GetParent
*
* @param	
* @return	AL_TreeNodeSeq<T>*	
* @note parent node pointer, not to manager memory
* @attention 
*/
template<typename T> AL_TreeNodeSeq<T>* 
AL_TreeNodeSeq<T>::GetParent() const
{
	return m_pParent;
}

/**
* SetParent
*
* @param	DWORD dwIndex <IN>
* @param	AL_TreeNodeSeq<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 )
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::SetParent(DWORD dwIndex, AL_TreeNodeSeq<T>* 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_TreeNodeSeq<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_TreeNodeSeq<T>::SetParentLeft(AL_TreeNodeSeq<T>* pParent)
{
	return SetParent(0x00, pParent);
}

/**
* SetParentRight
*
* @param	AL_TreeNodeSeq<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_TreeNodeSeq<T>::SetParentRight(AL_TreeNodeSeq<T>* pParent)
{
	return SetParent(pParent->GetDegree(), pParent);
}

/**
* Insert
*
* @param	DWORD dwIndex <IN>
* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the position
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::Insert(DWORD dwIndex, AL_TreeNodeSeq<T>* 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_ListSeq<AL_TreeNodeSeq<T>*> listDescendant;
			if (FALSE == GetDescendant(listDescendant)) {
				return FALSE;
			}
			AL_TreeNodeSeq<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_TreeNodeSeq<T>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the left
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::InsertLeft(AL_TreeNodeSeq<T>* pInsertChild)
{
	return Insert(0x00, pInsertChild);
}

/**
* InsertRight
*
* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the right
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::InsertRight(AL_TreeNodeSeq<T>* pInsertChild)
{
	return Insert(GetDegree(), pInsertChild);
}

/**
* GetChild
*
* @param	DWORD dwIndex <IN>
* @return	AL_TreeNodeSeq<T>*
* @note the dwIndex must is little than the node degree
* @attention
*/
template<typename T> AL_TreeNodeSeq<T>* 
AL_TreeNodeSeq<T>::GetChild(DWORD dwIndex) const
{
	AL_TreeNodeSeq<T>* pChild = NULL;
	if (TRUE == m_listChild.Get(pChild, dwIndex)) {
		return pChild;
	}
	return NULL;
}

/**
* GetChildLeft
*
* @param	
* @return	AL_TreeNodeSeq<T>*
* @note 
* @attention
*/
template<typename T> AL_TreeNodeSeq<T>* 
AL_TreeNodeSeq<T>::GetChildLeft() const
{
	return GetChild(0x00);
}

/**
* GetChildRight
*
* @param	
* @return	AL_TreeNodeSeq<T>*
* @note 
* @attention
*/
template<typename T> AL_TreeNodeSeq<T>* 
AL_TreeNodeSeq<T>::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<typename T> DWORD 
AL_TreeNodeSeq<T>::GetDegree() const
{
	return m_listChild.Length();
}

/**
* IsLeaf
*
* @param
* @return	BOOL
* @note leaf nodes or terminal nodes: degree 0 are called leaf nodes;
* @attention 
*/
template<typename T> BOOL 
AL_TreeNodeSeq<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_TreeNodeSeq<T>::IsBranch() const
{
	return (0x00 != GetDegree()) ? TRUE:FALSE;
}

/**
* IsParent
*
* @param	const AL_TreeNodeSeq<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_TreeNodeSeq<T>::IsParent(const AL_TreeNodeSeq<T>* pChild) const
{
	// 	AL_TreeNodeSeq<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_TreeNodeSeq<T>*>& listSibling <OUT>
* @return	BOOL
* @note sibling nodes: nodes with the same parent node is called mutual sibling;
* @attention 
*/
template<typename T> BOOL
AL_TreeNodeSeq<T>::GetSibling(AL_ListSeq<AL_TreeNodeSeq<T>*>& listSibling) const
{
	BOOL bSibling = FALSE;
	if (NULL == m_pParent) {
		//not parent node
		return bSibling;
	}

	listSibling.Clear();
	AL_ListSeq<AL_TreeNodeSeq<T>*>&	listParentChild = m_pParent->m_listChild;
	AL_TreeNodeSeq<T>* pParentChild = NULL;
	for (DWORD dwCnt=0; dwCnt<m_pParent->GetDegree(); 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_ListSeq<AL_TreeNodeSeq<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_TreeNodeSeq<T>::GetAncestor(AL_ListSeq<AL_TreeNodeSeq<T>*>& listAncestor) const
{
	if (NULL == m_pParent) {
		//not parent node
		return FALSE;
	}

	listAncestor.Clear();
	AL_TreeNodeSeq<T>* pParent = m_pParent;
	while (NULL != pParent) {
		listAncestor.InsertEnd(pParent);
		pParent = pParent->m_pParent;
	}
	return TRUE;
}

/**
* GetDescendant
*
* @param	AL_ListSeq<AL_TreeNodeSeq<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_TreeNodeSeq<T>::GetDescendant(AL_ListSeq<AL_TreeNodeSeq<T>*>& listDescendant) const
{
	if (TRUE == IsLeaf()) {
		//child node
		return FALSE;
	}
	
	listDescendant.Clear();
	AL_TreeNodeSeq<T>* pDescendant = NULL;
	for (DWORD dwCnt=0; dwCnt<GetDegree(); dwCnt++) {
		pDescendant = GetChild(dwCnt);
		if (NULL != pDescendant) {
			//get the child
			listDescendant.InsertEnd(pDescendant);
		}
		else {
			//error can not get the child
			return FALSE;
		}
	}

	//loop the all node in listDescendant
	DWORD dwDescendantLoop = 0x00;
	AL_TreeNodeSeq<T>* pDescendantLoop = NULL;
	while (TRUE == listDescendant.Get(pDescendant, dwDescendantLoop)) {
		dwDescendantLoop++;
		if (NULL != pDescendant) {
			for (DWORD dwCnt=0; dwCnt<pDescendant->GetDegree(); 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;
}

/**
*Assignment
*
* @param	const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq
* @return	AL_TreeNodeSeq<T>&
*/
template<typename T> AL_TreeNodeSeq<T>& 
AL_TreeNodeSeq<T>::operator = (const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq)
{
	m_dwLevel = cAL_TreeNodeSeq.m_dwLevel;
	m_data = cAL_TreeNodeSeq.m_data;
	m_pParent = cAL_TreeNodeSeq.m_pParent;
	m_listChild = cAL_TreeNodeSeq.m_listChild;
	return *this;
}
#endif // CXX_AL_TREENODESEQ_H
/* EOF */


AL_TreeSeq.h

/**
  @(#)$Id: AL_TreeSeq.h 51 2013-09-23 10:19:34Z 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-23 18:19:34 +0800 (周一, 23 九月 2013) $
  @Revision $Revision: 51 $
  @URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeSeq.h $
  @Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeSeq.h 51 2013-09-23 10:19:34Z xiaoting $
 */

#ifndef CXX_AL_TREESEQ_H
#define CXX_AL_TREESEQ_H

#ifndef CXX_AL_LISTSEQ_H
#include "AL_ListSeq.h"
#endif

#ifndef CXX_AL_QUEUESEQ_H
#include "AL_QueueSeq.h"
#endif

///
//			AL_TreeSeq
///

template<typename T> 
class AL_TreeSeq
{
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_TreeSeq(DWORD dwSize = TREESEQ_DEFAULTSIZE);

	/**
	* Destruction
	*
	* @param
	* @return
	* @note
	* @attention 
	*/
	~AL_TreeSeq();

	/**
	* IsEmpty
	*
	* @param VOID
	* @return BOOL
	* @note the tree has data?
	* @attention
	*/
	BOOL IsEmpty() const;
	
	/**
	* GetRootNode
	*
	* @param
	* @return	const AL_TreeNodeSeq<T>*
	* @note Get the root data
	* @attention 
	*/
	const AL_TreeNodeSeq<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();

	/**
	* 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_TreeNodeSeq<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_TreeNodeSeq<T>* pCurTreeNode) const;

	/**
	* GetAncestorAtNode
	*
	* @param	AL_ListSeq<T>& listAncestor <OUT>
	* @param	const AL_TreeNodeSeq<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_TreeNodeSeq<T>* pCurTreeNode) const;

	/**
	* GetDescendantAtNode
	*
	* @param	AL_ListSeq<T>& listDescendant <OUT>
	* @param	const AL_TreeNodeSeq<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_TreeNodeSeq<T>* pCurTreeNode) const;

	/**
	* InsertRoot
	*
	* @param	const T& tTemplate <IN> 
	* @return	BOOL
	* @note
	* @attention
	*/
	BOOL InsertRoot(const T& tTemplate);

	/**
	* InsertAtNode
	*
	* @param	AL_TreeNodeSeq<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_TreeNodeSeq<T>* pCurTreeNode, DWORD dwIndex, const T& tTemplate);

	/**
	* InsertLeftAtNode
	*
	* @param	AL_TreeNodeSeq<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_TreeNodeSeq<T>* pCurTreeNode, const T& tTemplate);

	/**
	* InsertRightAtNode
	*
	* @param	AL_TreeNodeSeq<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_TreeNodeSeq<T>* pCurTreeNode, const T& tTemplate);

	/**
	* GetChildNodeAtNode
	*
	* @param	const AL_TreeNodeSeq<T>* pCurTreeNode <IN>	
	* @param	DWORD dwIndex <IN>
	* @return	const AL_TreeNodeSeq<T>*
	* @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_TreeNodeSeq<T>* GetChildNodeAtNode(const AL_TreeNodeSeq<T>* pCurTreeNode, DWORD dwIndex) const;

	/**
	* GetChildNodeLeftAtNode
	*
	* @param	const AL_TreeNodeSeq<T>* pCurTreeNode <IN>	
	* @return	const AL_TreeNodeSeq<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_TreeNodeSeq<T>* GetChildNodeLeftAtNode(const AL_TreeNodeSeq<T>* pCurTreeNode) const;

	/**
	* GetChildNodeRightAtNode
	*
	* @param	const AL_TreeNodeSeq<T>* pCurTreeNode <IN>	
	* @return	const AL_TreeNodeSeq<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_TreeNodeSeq<T>*  GetChildNodeRightAtNode(const AL_TreeNodeSeq<T>* pCurTreeNode) const;

protected:
private:

	/**
	* 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_TreeSeq<T>& cAL_TreeSeq
	* @return
	*/
	AL_TreeSeq(const AL_TreeSeq<T>& cAL_TreeSeq);

	/**
	*Assignment
	*
	* @param	const AL_TreeSeq<T>& cAL_TreeSeq
	* @return	AL_TreeSeq<T>&
	*/
	AL_TreeSeq<T>& operator = (const AL_TreeSeq<T>& cAL_TreeSeq);

public:
protected:
private:
	AL_TreeNodeSeq<T>*					m_pTreeNode;			
	DWORD								m_dwMaxSize;

	DWORD								m_dwDegree;
	DWORD								m_dwHeight;
	DWORD								m_NumNodes;
	AL_TreeNodeSeq<T>*					m_pRootNode;
};

///
//			AL_TreeSeq
///

/**
* Construction
*
* @param	DWORD dwSize (default value: TREESEQ_DEFAULTSIZE)
* @return
* @note
* @attention
*/
template<typename T> 
AL_TreeSeq<T>::AL_TreeSeq(DWORD dwSize):
m_pTreeNode(NULL),
m_dwMaxSize(dwSize),
m_dwDegree(0xffffffff),
m_dwHeight(0x00),
m_NumNodes(0x00),
m_pRootNode(NULL)
{
	if (0x00 == m_dwMaxSize) {
		//for memory deal
		m_dwMaxSize = 1;
	}
	GetBuffer();
}

/**
* Destruction
*
* @param
* @return
* @note
* @attention 
*/
template<typename T> 
AL_TreeSeq<T>::~AL_TreeSeq()
{
	if (NULL != m_pTreeNode) {
		delete[] m_pTreeNode;
		m_pTreeNode = NULL;
	}
	m_dwMaxSize = 0x00;
	m_dwDegree = 0xffffffff;
	m_dwHeight = 0x00;
	m_NumNodes = 0x00;
	m_pRootNode = NULL;
}

/**
* IsEmpty
*
* @param VOID
* @return BOOL
* @note the tree has data?
* @attention
*/
template<typename T> BOOL 
AL_TreeSeq<T>::IsEmpty() const
{
	return (0x00 == m_NumNodes) ? TRUE:FALSE;
}

/**
* GetRootNode
*
* @param
* @return	const AL_TreeNodeSeq<T>*
* @note Get the root data
* @attention 
*/
template<typename T> const AL_TreeNodeSeq<T>* 
AL_TreeSeq<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_TreeSeq<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_TreeSeq<T>::GetHeight() const
{
	return m_dwHeight;
}

/**
* GetNodesNum
*
* @param
* @return	DWORD
* @note get the notes number of the tree 
* @attention 
*/
template<typename T> DWORD 
AL_TreeSeq<T>::GetNodesNum() const
{
	return m_NumNodes;
}

/**
* Clear
*
* @param
* @return	
* @note 
* @attention 
*/
template<typename T> VOID 
AL_TreeSeq<T>::Clear()
{
	m_dwDegree = 0xffffffff;
	m_dwHeight = 0x00;
	m_NumNodes = 0x00;
	m_pRootNode = NULL;
}

/**
* LevelOrderTraversal
*
* @param	AL_ListSeq<T>& listOrder <OUT>
* @return	BOOL
* @note Level-order traversal
* @attention 
*/
template<typename T> BOOL 
AL_TreeSeq<T>::LevelOrderTraversal(AL_ListSeq<T>& listOrder) const
{
	if (TRUE == IsEmpty()) {
		return FALSE;
	}

	if (NULL == m_pRootNode) {
		return FALSE;
	}
	listOrder.Clear();
	/*
	AL_ListSeq<AL_TreeNodeSeq<T>*> listNodeOrder;
	listNodeOrder.InsertEnd(m_pRootNode);
	//loop the all node
	DWORD dwNodeOrderLoop = 0x00;
	AL_TreeNodeSeq<T>* pNodeOrderLoop = NULL;
	AL_TreeNodeSeq<T>* pNodeOrderChild = NULL;
	while (TRUE == listNodeOrder.Get(pNodeOrderLoop, dwNodeOrderLoop)) {
		dwNodeOrderLoop++;
		if (NULL != pNodeOrderLoop) {
			listOrder.InsertEnd(pNodeOrderLoop->GetData());
			for (DWORD dwCnt=0; dwCnt<pNodeOrderLoop->GetDegree(); 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_QueueSeq<AL_TreeNodeSeq<T>*> queueOrder;
	queueOrder.Push(m_pRootNode);
	
	AL_TreeNodeSeq<T>* pNodeOrderLoop = NULL;
	AL_TreeNodeSeq<T>* pNodeOrderChild = NULL;
	while (FALSE == queueOrder.IsEmpty()) {
		if (TRUE == queueOrder.Pop(pNodeOrderLoop)) {
			if (NULL != pNodeOrderLoop) {
				listOrder.InsertEnd(pNodeOrderLoop->GetData()); 
				for (DWORD dwCnt=0; dwCnt<pNodeOrderLoop->GetDegree(); dwCnt++) {
					pNodeOrderChild = pNodeOrderLoop->GetChild(dwCnt);
					if (NULL != pNodeOrderChild) {
						queueOrder.Push(pNodeOrderChild);
					}
				}
			}
			else {
				return FALSE;
			}
		}
		else {
			return FALSE;
		}
	}
	return TRUE;
}


/**
* GetSiblingAtNode
*
* @param	AL_ListSeq<T>& listSibling <OUT>
* @param	const AL_TreeNodeSeq<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_TreeSeq<T>::GetSiblingAtNode(AL_ListSeq<T>& listSibling, const AL_TreeNodeSeq<T>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeSeq<T>*> listTreeNodeSibling;
	if (FALSE == pCurTreeNode->GetSibling(listTreeNodeSibling)) {
		return FALSE;
	}
	//clear listSibling 
	listSibling.Clear();
	AL_TreeNodeSeq<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_TreeNodeSeq<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_TreeSeq<T>::GetAncestorAtNode(AL_ListSeq<T>& listAncestor, const AL_TreeNodeSeq<T>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeSeq<T>*> listTreeNodeAncestor;
	if (FALSE == pCurTreeNode->GetAncestor(listTreeNodeAncestor)) {
		return FALSE;
	}
	//clear listAncestor 
	listAncestor.Clear();
	AL_TreeNodeSeq<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_TreeNodeSeq<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_TreeSeq<T>::GetDescendantAtNode(AL_ListSeq<T>& listDescendant, const AL_TreeNodeSeq<T>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeSeq<T>*> listTreeNodeDescendant;
	if (FALSE == pCurTreeNode->GetDescendant(listTreeNodeDescendant)) {
		return FALSE;
	}
	//clear listAncestor 
	listDescendant.Clear();
	AL_TreeNodeSeq<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_TreeSeq<T>::InsertRoot(const T& tTemplate)
{
	return InsertAtNode(NULL, 0x00, tTemplate);
}

/**
* InsertAtNode
*
* @param	AL_TreeNodeSeq<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_TreeSeq<T>::InsertAtNode(AL_TreeNodeSeq<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_NumNodes].SetData(tTemplate);
			m_pTreeNode[m_NumNodes].SetLevel(0x00);

			m_pRootNode = &m_pTreeNode[m_NumNodes];
			m_dwDegree = 0x00;
			m_dwHeight = 0x00;			//empty tree 0xffffffff (-1)
			m_NumNodes++;
			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_NumNodes].SetData(tTemplate);
	m_pTreeNode[m_NumNodes].SetLevel(pCurTreeNode->GetLevel() + 1);
	if (FALSE ==  pCurTreeNode->Insert(dwIndex, &m_pTreeNode[m_NumNodes])) {
		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_NumNodes].GetLevel() > m_dwHeight) {
		m_dwHeight = m_pTreeNode[m_NumNodes].GetLevel();
	}
	m_NumNodes++;

	return TRUE;
}

/**
* InsertLeftAtNode
*
* @param	AL_TreeNodeSeq<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_TreeSeq<T>::InsertLeftAtNode(AL_TreeNodeSeq<T>* pCurTreeNode, const T& tTemplate)
{
	return InsertAtNode(pCurTreeNode, 0x00, tTemplate);
}

/**
* InsertRightAtNode
*
* @param	AL_TreeNodeSeq<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_TreeSeq<T>::InsertRightAtNode(AL_TreeNodeSeq<T>* pCurTreeNode, const T& tTemplate)
{
	return InsertAtNode(pCurTreeNode, pCurTreeNode->GetDegree(), tTemplate);
}

/**
* GetChildNodeAtNode
*
* @param	const AL_TreeNodeSeq<T>* pCurTreeNode <IN>	
* @param	DWORD dwIndex <IN>
* @return	const AL_TreeNodeSeq<T>*
* @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<typename T> const AL_TreeNodeSeq<T>* 
AL_TreeSeq<T>::GetChildNodeAtNode(const AL_TreeNodeSeq<T>* pCurTreeNode, DWORD dwIndex) const
{
	if (NULL == pCurTreeNode) {
		return NULL;
	}

	return pCurTreeNode->GetChild(dwIndex);
}

/**
* GetChildNodeLeftAtNode
*
* @param	const AL_TreeNodeSeq<T>* pCurTreeNode <IN>	
* @return	const AL_TreeNodeSeq<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_TreeNodeSeq<T>* 
AL_TreeSeq<T>::GetChildNodeLeftAtNode(const AL_TreeNodeSeq<T>* pCurTreeNode) const
{
	return GetChildNodeAtNode(pCurTreeNode, 0x00);
}

/**
* GetChildNodeRightAtNode
*
* @param	const AL_TreeNodeSeq<T>* pCurTreeNode <IN>	
* @return	const AL_TreeNodeSeq<T>*
* @note get the current tree node (pCurTreeNode)'s child node at the position (right)
* @attention
*/
template<typename T> const AL_TreeNodeSeq<T>* 
AL_TreeSeq<T>::GetChildNodeRightAtNode(const AL_TreeNodeSeq<T>* pCurTreeNode) const
{
	return GetChildNodeAtNode(pCurTreeNode, pCurTreeNode->GetDegree());
}

/**
* 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_TreeSeq<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_TreeNodeSeq<T>[m_dwMaxSize];
		}
		return;
	}

	//we need to get more buffer, store the previous pointer
	AL_TreeNodeSeq<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_TreeNodeSeq<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_TreeSeq<T>::IsFull() const
{
	return (m_dwMaxSize <= GetNodesNum()) ? TRUE:FALSE;
}
#endif // CXX_AL_TREESEQ_H
/* EOF */



测试代码

#ifdef TEST_AL_TREESEQ
	AL_TreeSeq<DWORD> cTreeSeq(100);
	BOOL bEmpty = cTreeSeq.IsEmpty();
	std::cout<<bEmpty<<std::endl;
	const AL_TreeNodeSeq<DWORD>* pConstRootNode = cTreeSeq.GetRootNode();
	AL_TreeNodeSeq<DWORD>* pRootNode = const_cast<AL_TreeNodeSeq<DWORD>*>(pConstRootNode);
	std::cout<<pRootNode<<std::endl;
	DWORD dwDegree = cTreeSeq.GetDegree();
	std::cout<<dwDegree<<std::endl;
	DWORD dwHeight = cTreeSeq.GetHeight();
	std::cout<<dwHeight<<std::endl;
	DWORD dwNodesNum = cTreeSeq.GetNodesNum();
	std::cout<<dwNodesNum<<std::endl;

	cTreeSeq.InsertRoot(0);
	pConstRootNode = cTreeSeq.GetRootNode();
	pRootNode = const_cast<AL_TreeNodeSeq<DWORD>*>(pConstRootNode);
	std::cout<<pRootNode<<std::endl;
	
	cTreeSeq.InsertAtNode(pRootNode, 0x00, 10);

	const AL_TreeNodeSeq<DWORD>* pConstTreeNode = cTreeSeq.GetChildNodeAtNode(pRootNode, 0x00);
	AL_TreeNodeSeq<DWORD>* pTreeNode = const_cast<AL_TreeNodeSeq<DWORD>*>(pConstTreeNode);
	std::cout<<pTreeNode<<std::endl;
	
	cTreeSeq.InsertAtNode(pTreeNode, 0x00, 21);
	cTreeSeq.InsertLeftAtNode(pTreeNode, 20);
	cTreeSeq.InsertRightAtNode(pTreeNode, 22);
	cTreeSeq.InsertAtNode(pTreeNode, 0x03, 23);

	const AL_TreeNodeSeq<DWORD>* pConstTreeNode20 = cTreeSeq.GetChildNodeAtNode(pTreeNode, 0x00);
	AL_TreeNodeSeq<DWORD>* pTreeNode20 = const_cast<AL_TreeNodeSeq<DWORD>*>(pConstTreeNode20);
	std::cout<<pTreeNode<<std::endl;
	
	cTreeSeq.InsertAtNode(pTreeNode20, 0x00, 31);
	cTreeSeq.InsertLeftAtNode(pTreeNode20, 30);
	cTreeSeq.InsertRightAtNode(pTreeNode20, 32);
	cTreeSeq.InsertAtNode(pTreeNode20, 0x03, 33);

	const AL_TreeNodeSeq<DWORD>* pConstTreeNode33 = cTreeSeq.GetChildNodeAtNode(pTreeNode20, 0x3);
	AL_TreeNodeSeq<DWORD>* pTreeNode33 = const_cast<AL_TreeNodeSeq<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_TreeNodeSeq<DWORD>*	pChild = NULL;
	pChild = cTreeSeq.GetChildNodeAtNode(pTreeNode, 0x01);
	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 = cTreeSeq.GetChildNodeAtNode(pTreeNode, 0x00);
	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 = cTreeSeq.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 = cTreeSeq.GetChildNodeAtNode(pTreeNode, 0x03);
	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 = cTreeSeq.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 = cTreeSeq.IsEmpty();
	std::cout<<bEmpty<<std::endl;
	dwDegree = cTreeSeq.GetDegree();
	std::cout<<dwDegree<<std::endl;
	dwHeight = cTreeSeq.GetHeight();
	std::cout<<dwHeight<<std::endl;
	dwNodesNum = cTreeSeq.GetNodesNum();
	std::cout<<dwNodesNum<<std::endl;

	AL_ListSeq<DWORD> cListSeq;
	DWORD dwData;
	BOOL bSibling = cTreeSeq.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 = cTreeSeq.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 = cTreeSeq.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 = cTreeSeq.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 = cTreeSeq.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 = cTreeSeq.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 = cTreeSeq.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();

#endif








  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值