※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)

AVL树/自平衡二叉查找树

        在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。

        节点的平衡因子是它的左子树的高度减去它的右子树的高度(有时相反)。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。


插入
        向AVL树插入可以通过如同它是未平衡的二叉查找树一样把给定的值插入树中,接着自底向上向根节点折回,于在插入期间成为不平衡的所有节点上进行旋转来完成。因为折回到根节点的路途上最多有 1.5 乘 log n 个节点,而每次 AVL 旋转都耗费恒定的时间,插入处理在整体上耗费 O(log n) 时间。 在平衡的的二叉排序树Balanced BST上插入一个新的数据元素e的递归算法可描述如下: 若BBST为空树,则插入一个数据元素为e的新结点作为BBST的根结点,树的深度增1; 若e的关键字和BBST的根结点的关键字相等,则不进行; 若e的关键字小于BBST的根结点的关键字,而且在BBST的左子树中不存在和e有相同关键字的结点,则将e插入在BBST的左子树上,并且当插入之后的左子树深度增加(+1)时,分别就下列不同情况处理之:BBST的根结点的平衡因子为-1(右子树的深度大于左子树的深度,则将根结点的平衡因子更改为0,BBST的深度不变; BBST的根结点的平衡因子为0(左、右子树的深度相等):则将根结点的平衡因子更改为1,BBST的深度增1; BBST的根结点的平衡因子为1(左子树的深度大于右子树的深度):则若BBST的左子树根结点的平衡因子为1:则需进行单向右旋平衡处理,并且在右旋处理之后,将根结点和其右子树根结点的平衡因子更改为0,树的深度不变; 若e的关键字大于BBST的根结点的关键字,而且在BBST的右子树中不存在和e有相同关键字的结点,则将e插入在BBST的右子树上,并且当插入之后的右子树深度增加(+1)时,分别就不同情况处理之。

插入旋转

 平衡二叉树在进行插入操作的时候可能出现不平衡的情况,AVL树即是一种自平衡的二叉树,它通过旋转不平衡的节点来使二叉树重新保持平衡,并且查找、插入和删除操作在平均和最坏情况下时间复杂度都是O(log n)

       AVL树的旋转一共有四种情形,注意所有旋转情况都是围绕着使得二叉树不平衡的第一个节点展开的。

 1. LL型

    平衡二叉树某一节点的左孩子的左子树上插入一个新的节点,使得该节点不再平衡。这时只需要把树向右旋转一次即可,如图所示,原A的左孩子B变为父结点,A变为其右孩子,而原B的右子树变为A的左子树,注意旋转之后Brh是A的左子树(图上忘在A于Brh之间标实线)

    不平衡点A旋转点B

《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

 2. RR型

    平衡二叉树某一节点的右孩子的右子树上插入一个新的节点,使得该节点不再平衡。这时只需要把树向左旋转一次即可,如图所示,原A右孩子B变为父结点,A变为其左孩子,而原B的左子树Blh将变为A的右子树。

    不平衡点A旋转点B

《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

 3. LR型

      平衡二叉树某一节点的左孩子的右子树上插入一个新的节点,使得该节点不再平衡。这时需要旋转两次,仅一次的旋转是不能够使二叉树再次平衡。如图所示,在B节点按照RR型向左旋转一次之后,二叉树在A节点仍然不能保持平衡,这时还需要再向右旋转一次。

    不平衡点A旋转点B                                    不平衡点A旋转点C

《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

 4. RL型

      平衡二叉树某一节点的右孩子的左子树上插入一个新的节点,使得该节点不再平衡。同样,这时需要旋转两次,旋转方向刚好同LR型相反。

    不平衡点A旋转点B                                    不平衡点A旋转点C

《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

删除
        从AVL树中删除可以通过把要删除的节点向下旋转成一个叶子节点,接着直接剪除这个叶子节点来完成。因为在旋转成叶子节点期间最多有 log n个节点被旋转,而每次 AVL 旋转耗费恒定的时间,删除处理在整体上耗费 O(log n) 时间。


查找

        在AVL树中查找同在一般BST完全一样的进行,所以耗费 O(log n) 时间,因为AVL树总是保持平衡的。不需要特殊的准备,树的结构不会由于查询而改变。(这是与伸展树查找相对立的,它会因为查找而变更树结构。)


==============================================================================================

二叉搜索树(二叉查找树)
        二叉查找树(Binary Search Tree),或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

原理

        二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树的存储结构。中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).

算法

查找算法
在二叉排序树b中查找x的过程为:
若b是空树,则搜索失败,否则:
若x等于b的根结点的数据域之值,则查找成功;否则:
若x小于b的根结点的数据域之值,则搜索左子树;否则:
查找右子树。

/**
* GetNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
* @param	const KEY& tKey <IN> 
* @return	const AL_TreeNodeBinSearchSeq<T, KEY>* 
* @note		for Recursion search
* @attention
*/
template<typename T, typename KEY> const AL_TreeNodeBinSearchSeq<T, KEY>* 
AL_TreeBinSearchSeq<T, KEY>::GetNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, const KEY& tKey)
{
	if (NULL == pCurTreeNode) {
		return NULL;
	}

	if (tKey < pCurTreeNode->GetKey()) {
		//search the left child
		return GetNode(pCurTreeNode->GetChildLeft(), tKey);
	}
	else if (pCurTreeNode->GetKey() < tKey) {
		//search the right child
		return GetNode(pCurTreeNode->GetChildRight(), tKey);
	}
	else {
		//find it, pCurTreeNode->GetKey() == tKey
		return pCurTreeNode;
	}
	
	//Recursion End
	return NULL;
}

插入算法
向一个二叉排序树b中插入一个结点s的算法,过程为:
若b是空树,则将s所指结点作为根结点插入,否则:
若s->data等于b的根结点的数据域之值,则返回,否则:
若s->data小于b的根结点的数据域之值,则把s所指结点插入到左子树中,否则:
把s所指结点插入到右子树中。

  • 1.若当前的二叉查找树为空,则插入的元素为根节点,
  • 2.若插入的元素值小于根节点值,则将元素插入到左子树中,
  • 3.若插入的元素值不小于根节点值,则将元素插入到右子树中。
/**
* Insert
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pRecursionNode <IN> 
* @param	const T& tData <IN> 
* @param	const KEY& tKey <IN> 
* @return	BOOL
* @note		for Recursion Insert
* @attention if pRecursionNode may be NULL
*/
template<typename T, typename KEY> BOOL 
AL_TreeBinSearchSeq<T, KEY>::Insert(const AL_TreeNodeBinSearchSeq<T, KEY>* pRecursionNode, const T& tData, const KEY& tKey)
{
	if (TRUE == IsEmpty()) {
		if (NULL != pRecursionNode) {
			//empty, but has the node
			return FALSE;
		}
		//has no root node, insert as root node
		return InsertAtNode(NULL, 0x00, tData, tKey);
	}
	
	static const AL_TreeNodeBinSearchSeq<T, KEY>* pRecursionNodePre = NULL;		//store the previous node of recursion
	if (NULL == pRecursionNode) {
		if (NULL == pRecursionNodePre) {
			//some thing wrong
			return FALSE;
		}
		//inset to the current tree node
		if (NULL == pRecursionNodePre->GetChildLeft() && NULL == pRecursionNodePre->GetChildRight()) {
			//left and right all NULL
			if (tKey < pRecursionNodePre->GetKey()) {
				//insert the left child
				return InsertLeftAtNode(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRecursionNodePre), tData, tKey);
			}
			else if (pRecursionNodePre->GetKey() < tKey) {
				//insert the right child
				return InsertRightAtNode(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRecursionNodePre), tData, tKey);
			}
			else {
				//error, can not have the same key
				return FALSE;
			}
		}
		else if (NULL == pRecursionNodePre->GetChildLeft() && NULL != pRecursionNodePre->GetChildRight()) {
			//left NULL, right not NULL
			if (tKey < pRecursionNodePre->GetKey()) {
				//insert the left child
				return InsertLeftAtNode(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRecursionNodePre), tData, tKey);
			}
			else {
				//error, can not have the same key
				return FALSE;
			}
		}
		else if (NULL != pRecursionNodePre->GetChildLeft() && NULL == pRecursionNodePre->GetChildRight()) {
			//left not NULL, right NULL
			if (pRecursionNodePre->GetKey() < tKey) {
				return InsertRightAtNode(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRecursionNodePre), tData, tKey);
			}
			else {
				return FALSE;
			}
		}
		else {
			//left not NULL, right not NULL
			return FALSE;
		}
	}
	pRecursionNodePre = pRecursionNode;
	if (tKey < pRecursionNode->GetKey()) {
		//recursion the left child (Insert)
		return Insert(pRecursionNode->GetChildLeft(), tData, tKey);
	}
	else if (pRecursionNode->GetKey() < tKey) {
		//recursion the right child (Insert)
		return Insert(pRecursionNode->GetChildRight(), tData, tKey);
	}
	else {
		//error, can not have the same key
		return FALSE;
	}

	//Recursion End
	return FALSE;
}

删除算法

在二叉排序树删去一个结点,分三种情况讨论:
若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。
若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树或右子树即可,作此修改也不破坏二叉排序树的特性。
若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,可以有两种做法:其一是令*p的左子树为*f的左子树,*s为*f左子树的最右下的结点,而*p的右子树为*s的右子树;其二是令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)。

1.p为叶子节点,直接删除该节点,再修改其父节点的指针(注意分是根节点和不是根节点),如图a。
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

2.p为单支节点(即只有左子树或右子树)。让p的子树与p的父亲节点相连,删除p即可;(注意分是根节点和不是根节点);如图b。
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

3.p的左子树和右子树均不空。找到p的后继y,因为y一定没有左子树,所以可以删除y,并让y的父亲节点成为y的右子树的父亲节点,并用y的值代替p的值;或者方法二是找到p的前驱x,x一定没有右子树,所以可以删除x,并让x的父亲节点成为y的左子树的父亲节点。如图c。

《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

//insert current node's child to the replace node
		pChildLeft->RemoveParent();
		pChildRight->RemoveParent();
		if (pReplace != pChildLeft) {
			if (FALSE == pReplace->InsertLeft(pChildLeft)) {
					return FALSE;
			}
		}
		if (pReplace != pChildRight) {
			if (FALSE == pReplace->InsertRight(pChildRight)) {
				return FALSE;
			}
		}

ps: 注意替代的结点是否为删除结点的子结点。不然会将自己本身作为自己的子结点插入。

======================================================================================================

二叉树

        在计算机科学中,二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用作二叉查找树和二叉堆或是二叉排序树。二叉树的每个结点至多只有二棵子树(不存在出度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2的 i -1次方个结点;深度为k的二叉树至多有2^(k) -1个结点;对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为,出度为2的结点数为,则=+ 1。

基本形态
          二叉树也是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:
                  (1)空二叉树——(a);  
                  (2)只有一个根结点的二叉树——(b);
                  (3)只有左子树——(c);
                  (4)只有右子树——(d);
                  (5)完全二叉树——(e)
         注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。

重要概念
         (1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
         (2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
         (3)深度——二叉树的层数,就是高度。

性质
         (1) 在二叉树中,第i层的结点总数不超过2^(i-1);
         (2) 深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点;
         (3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
         (4) 具有n个结点的完全二叉树的深度为int(log2n)+1
         (5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
                  若I为结点编号则 如果I>1,则其父结点的编号为I/2;
                  如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;
                  如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。
         (6)给定N个节点,能构成h(N)种不同的二叉树。
                  h(N)为卡特兰数的第N项。h(n)=C(n,2*n)/(n+1)。
         (7)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i


1.完全二叉树 (Complete Binary Tree)
         若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层从右向左连续缺若干结点,这就是完全二叉树。


2.满二叉树 (Full Binary Tree)
         一个高度为h的二叉树包含正是2^h-1元素称为满二叉树。


二叉树四种遍历

        1.先序遍历 (仅二叉树)
                指先访问根,然后访问孩子的遍历方式

                非递归实现

                利用栈实现,先取根节点,处理节点,然后依次遍历左节点,遇到有右节点压入栈,向左走到尽头。然后从栈中取出右节点,处理右子树。

[cpp] 
view plain
copy
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

  1. <span style=“font-size:14px”><em>/**</em></span>* PreOrderTraversal 
  2. * 
  3. * @param    AL_ListSeq<T>& listOrder <OUT> 
  4. * @return   BOOL 
  5. * @note Pre-order traversal 
  6. * @attention  
  7. */  
  8. template<typename T> BOOL   
  9. AL_TreeBinSeq<T>::PreOrderTraversal(AL_ListSeq<T>& listOrder) const  
  10. {  
  11.     if (NULL == m_pRootNode) {  
  12.         return FALSE;  
  13.     }  
  14.   
  15.     listOrder.Clear();  
  16.   
  17.     //Recursion Traversal  
  18.     PreOrderTraversal(m_pRootNode, listOrder);  
  19.     return TRUE;  
  20.       
  21.     //Not Recursion Traversal  
  22.     AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStack;  
  23.     AL_TreeNodeBinSeq<T>* pTreeNode = m_pRootNode;  
  24.   
  25.     while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {  
  26.         while (NULL != pTreeNode) {  
  27.             listOrder.InsertEnd(pTreeNode->GetData());  
  28.             if (NULL != pTreeNode->GetChildRight()) {  
  29.                 //push the child right to stack  
  30.                 cStack.Push(pTreeNode->GetChildRight());  
  31.             }  
  32.             pTreeNode = pTreeNode->GetChildLeft();  
  33.         }  
  34.   
  35.         if (TRUE == cStack.Pop(pTreeNode)) {  
  36.             if (NULL == pTreeNode) {  
  37.                 return FALSE;  
  38.             }  
  39.         }  
  40.         else {  
  41.             return FALSE;  
  42.         }  
  43.           
  44.     }  
  45.     return TRUE;  
  46. }  

                递归实现

[cpp] 
view plain
copy
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

  1. /** 
  2. * PreOrderTraversal 
  3. * 
  4. * @param    const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>    
  5. * @param    AL_ListSeq<T>& listOrder <OUT> 
  6. * @return   VOID 
  7. * @note Pre-order traversal 
  8. * @attention Recursion Traversal 
  9. */  
  10. template<typename T> VOID   
  11. AL_TreeBinSeq<T>::PreOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const  
  12. {  
  13.     if (NULL == pCurTreeNode) {  
  14.         return;  
  15.     }  
  16.     //Do Something with root  
  17.     listOrder.InsertEnd(pCurTreeNode->GetData());  
  18.   
  19.     if(NULL != pCurTreeNode->GetChildLeft()) {  
  20.         PreOrderTraversal(pCurTreeNode->GetChildLeft(), listOrder);  
  21.     }  
  22.   
  23.     if(NULL != pCurTreeNode->GetChildRight()) {  
  24.         PreOrderTraversal(pCurTreeNode->GetChildRight(), listOrder);  
  25.     }  
  26. }  


        2.中序遍历(仅二叉树)

                指先访问左(右)孩子,然后访问根,最后访问右(左)孩子的遍历方式

                非递归实现

                利用栈实现,先取根节点,然后依次遍历左节点,将左节点压入栈,向左走到尽头。然后从栈中取出左节点,处理节点。然后处理其右子树。

[cpp] 
view plain
copy
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

  1. /** 
  2. * InOrderTraversal 
  3. * 
  4. * @param    AL_ListSeq<T>& listOrder <OUT> 
  5. * @return   BOOL 
  6. * @note In-order traversal 
  7. * @attention  
  8. */  
  9. template<typename T> BOOL   
  10. AL_TreeBinSeq<T>::InOrderTraversal(AL_ListSeq<T>& listOrder) const  
  11. {  
  12.     if (NULL == m_pRootNode) {  
  13.         return FALSE;  
  14.     }  
  15.   
  16.     listOrder.Clear();  
  17.       
  18.     //Recursion Traversal  
  19.     InOrderTraversal(m_pRootNode, listOrder);  
  20.     return TRUE;  
  21.   
  22.     //Not Recursion Traversal  
  23.     AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStack;  
  24.     AL_TreeNodeBinSeq<T>* pTreeNode = m_pRootNode;  
  25.   
  26.     while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {  
  27.         while (NULL != pTreeNode) {  
  28.             cStack.Push(pTreeNode);  
  29.             pTreeNode = pTreeNode->GetChildLeft();  
  30.         }  
  31.   
  32.         if (TRUE == cStack.Pop(pTreeNode)) {  
  33.             if (NULL !=  pTreeNode) {  
  34.                 listOrder.InsertEnd(pTreeNode->GetData());  
  35.                 if (NULL != pTreeNode->GetChildRight()){  
  36.                     //child right exist, push the node, and loop it’s left child to push  
  37.                     pTreeNode = pTreeNode->GetChildRight();  
  38.                 }  
  39.                 else {  
  40.                     //to pop the node in the stack  
  41.                     pTreeNode = NULL;  
  42.                 }  
  43.             }  
  44.             else {  
  45.                 return FALSE;  
  46.             }  
  47.         }  
  48.         else {  
  49.             return FALSE;  
  50.         }  
  51.     }  
  52.   
  53.     return TRUE;  
  54. }  

                递归实现

[cpp] 
view plain
copy
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

  1. /** 
  2. * InOrderTraversal 
  3. * 
  4. * @param    const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>    
  5. * @param    AL_ListSeq<T>& listOrder <OUT> 
  6. * @return   VOID 
  7. * @note In-order traversal 
  8. * @attention Recursion Traversal 
  9. */  
  10. template<typename T> VOID   
  11. AL_TreeBinSeq<T>::InOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const  
  12. {  
  13.     if (NULL == pCurTreeNode) {  
  14.         return;  
  15.     }  
  16.       
  17.     if(NULL != pCurTreeNode->GetChildLeft()) {  
  18.         InOrderTraversal(pCurTreeNode->GetChildLeft(), listOrder);  
  19.     }  
  20.   
  21.     //Do Something with root  
  22.     listOrder.InsertEnd(pCurTreeNode->GetData());  
  23.   
  24.     if(NULL != pCurTreeNode->GetChildRight()) {  
  25.         InOrderTraversal(pCurTreeNode->GetChildRight(), listOrder);  
  26.     }  
  27. }  

        3.后序遍历(仅二叉树)

                指先访问孩子,然后访问根的遍历方式

                非递归实现

                利用栈实现,先取根节点,然后依次遍历左节点,将左节点压入栈,向左走到尽头。然后从栈中取出左节点,处理节点。处理其右节点,还需要记录已经使用过的节点,比较麻烦和复杂。大致思路如下:

  • 1.找到最左边的子节点
  • 2.如果最左边的子节点有右节点,处理右节点(类似1)
  • 3.从栈里弹出节点处理
  • 3.当碰到左右节点都存在的节点时,需要进行记录了回归节点了。然后以当前节点的右子树进行处理
  • 4.碰到回归节点时,把当前的最后一个元素消除(因为后面还会回归到这个点的)。

[cpp] 
view plain
copy
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

  1. /** 
  2. * PostOrderTraversal 
  3. * 
  4. * @param    AL_ListSeq<T>& listOrder <OUT> 
  5. * @return   BOOL 
  6. * @note Post-order traversal 
  7. * @attention  
  8. */  
  9. template<typename T> BOOL   
  10. AL_TreeBinSeq<T>::PostOrderTraversal(AL_ListSeq<T>& listOrder) const  
  11. {  
  12.     if (NULL == m_pRootNode) {  
  13.         return FALSE;  
  14.     }  
  15.   
  16.     listOrder.Clear();  
  17.   
  18.     //Recursion Traversal  
  19.     PostOrderTraversal(m_pRootNode, listOrder);  
  20.     return TRUE;  
  21.   
  22.     //Not Recursion Traversal  
  23.     AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStack;  
  24.     AL_TreeNodeBinSeq<T>* pTreeNode = m_pRootNode;  
  25.     AL_StackSeq<AL_TreeNodeBinSeq<T>*> cStackReturn;  
  26.     AL_TreeNodeBinSeq<T>* pTreeNodeReturn = NULL;  
  27.   
  28.     while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {  
  29.         while (NULL != pTreeNode) {  
  30.             cStack.Push(pTreeNode);  
  31.             if (NULL != pTreeNode->GetChildLeft()) {  
  32.                 pTreeNode = pTreeNode->GetChildLeft();  
  33.             }  
  34.             else {  
  35.                 //has not left child, get the right child  
  36.                 pTreeNode = pTreeNode->GetChildRight();  
  37.             }  
  38.         }  
  39.   
  40.         if (TRUE == cStack.Pop(pTreeNode)) {  
  41.             if (NULL !=  pTreeNode) {  
  42.                 listOrder.InsertEnd(pTreeNode->GetData());  
  43.                 if (NULL != pTreeNode->GetChildLeft() && NULL != pTreeNode->GetChildRight()){  
  44.                     //child right exist  
  45.                     cStackReturn.Top(pTreeNodeReturn);  
  46.                     if (pTreeNodeReturn != pTreeNode) {  
  47.                         listOrder.RemoveAt(listOrder.Length()-1);  
  48.                         cStack.Push(pTreeNode);  
  49.                         cStackReturn.Push(pTreeNode);  
  50.                         pTreeNode = pTreeNode->GetChildRight();  
  51.                     }  
  52.                     else {  
  53.                         //to pop the node in the stack  
  54.                         cStackReturn.Pop(pTreeNodeReturn);  
  55.                         pTreeNode = NULL;  
  56.                     }  
  57.                 }  
  58.                 else {  
  59.                     //to pop the node in the stack  
  60.                     pTreeNode = NULL;  
  61.                 }  
  62.             }  
  63.             else {  
  64.                 return FALSE;  
  65.             }  
  66.         }  
  67.         else {  
  68.             return FALSE;  
  69.         }  
  70.     }  
  71.   
  72.     return TRUE;  
  73. }  

                递归实现

[cpp] 
view plain
copy
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

  1. /** 
  2. * PostOrderTraversal 
  3. * 
  4. * @param    const AL_TreeNodeBinSeq<T>* pCurTreeNode <IN>    
  5. * @param    AL_ListSeq<T>& listOrder <OUT> 
  6. * @return   VOID 
  7. * @note Post-order traversal 
  8. * @attention Recursion Traversal 
  9. */  
  10. template<typename T> VOID   
  11. AL_TreeBinSeq<T>::PostOrderTraversal(const AL_TreeNodeBinSeq<T>* pCurTreeNode, AL_ListSeq<T>& listOrder) const  
  12. {  
  13.     if (NULL == pCurTreeNode) {  
  14.         return;  
  15.     }  
  16.   
  17.     if(NULL != pCurTreeNode->GetChildLeft()) {  
  18.         PostOrderTraversal(pCurTreeNode->GetChildLeft(), listOrder);  
  19.     }  
  20.   
  21.     if(NULL != pCurTreeNode->GetChildRight()) {  
  22.         PostOrderTraversal(pCurTreeNode->GetChildRight(), listOrder);  
  23.     }  
  24.   
  25.     //Do Something with root  
  26.     listOrder.InsertEnd(pCurTreeNode->GetData());  
  27. }  

       
 4.层次遍历

                一层一层的访问,所以一般用广度优先遍历。

                非递归实现

利用链表或者队列均可实现,先取根节点压入链表或者队列,依次从左往右体访问子节点,压入链表或者队列。直至处理完所有节点。

[cpp] 
view plain
copy
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

  1. /** 
  2. * LevelOrderTraversal 
  3. * 
  4. * @param    AL_ListSeq<T>& listOrder <OUT> 
  5. * @return   BOOL 
  6. * @note Level-order traversal 
  7. * @attention  
  8. */  
  9. template<typename T> BOOL   
  10. AL_TreeBinSeq<T>::LevelOrderTraversal(AL_ListSeq<T>& listOrder) const  
  11. {  
  12.     if (TRUE == IsEmpty()) {  
  13.         return FALSE;  
  14.     }  
  15.   
  16.     if (NULL == m_pRootNode) {  
  17.         return FALSE;  
  18.     }  
  19.     listOrder.Clear();  
  20.     /* 
  21.     AL_ListSeq<AL_TreeNodeBinSeq<T>*> listNodeOrder; 
  22.     listNodeOrder.InsertEnd(m_pRootNode); 
  23.     //loop the all node 
  24.     DWORD dwNodeOrderLoop = 0x00; 
  25.     AL_TreeNodeBinSeq<T>* pNodeOrderLoop = NULL; 
  26.     AL_TreeNodeBinSeq<T>* pNodeOrderChild = NULL; 
  27.     while (TRUE == listNodeOrder.Get(pNodeOrderLoop, dwNodeOrderLoop)) { 
  28.         dwNodeOrderLoop++; 
  29.         if (NULL != pNodeOrderLoop) { 
  30.             listOrder.InsertEnd(pNodeOrderLoop->GetData()); 
  31.             pNodeOrderChild = pNodeOrderLoop->GetChildLeft(); 
  32.             if (NULL != pNodeOrderChild) { 
  33.                 queueOrder.Push(pNodeOrderChild); 
  34.             } 
  35.             pNodeOrderChild = pNodeOrderLoop->GetChildRight(); 
  36.             if (NULL != pNodeOrderChild) { 
  37.                 queueOrder.Push(pNodeOrderChild); 
  38.             } 
  39.         } 
  40.         else { 
  41.             //error 
  42.             return FALSE; 
  43.         } 
  44.     } 
  45.     return TRUE; 
  46.     */  
  47.       
  48.     AL_QueueSeq<AL_TreeNodeBinSeq<T>*> queueOrder;  
  49.     queueOrder.Push(m_pRootNode);  
  50.       
  51.     AL_TreeNodeBinSeq<T>* pNodeOrderLoop = NULL;  
  52.     AL_TreeNodeBinSeq<T>* pNodeOrderChild = NULL;  
  53.     while (FALSE == queueOrder.IsEmpty()) {  
  54.         if (TRUE == queueOrder.Pop(pNodeOrderLoop)) {  
  55.             if (NULL != pNodeOrderLoop) {  
  56.                 listOrder.InsertEnd(pNodeOrderLoop->GetData());   
  57.                 pNodeOrderChild = pNodeOrderLoop->GetChildLeft();  
  58.                 if (NULL != pNodeOrderChild) {  
  59.                     queueOrder.Push(pNodeOrderChild);  
  60.                 }  
  61.                 pNodeOrderChild = pNodeOrderLoop->GetChildRight();  
  62.                 if (NULL != pNodeOrderChild) {  
  63.                     queueOrder.Push(pNodeOrderChild);  
  64.                 }  
  65.             }  
  66.             else {  
  67.                 return FALSE;  
  68.             }  
  69.         }  
  70.         else {  
  71.             return FALSE;  
  72.         }  
  73.     }  
  74.     return TRUE;  
  75. }  

                
递归实现 (无)



======================================================================================================

树(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的子树。
  • 空集合也是树,称为空树。空树中没有结点。

        《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

树的四种遍历

        1.先序遍历 (仅二叉树)
                指先访问根,然后访问孩子的遍历方式

        2.中序遍历(仅二叉树)

                指先访问左(右)孩子,然后访问根,最后访问右(左)孩子的遍历方式

        3.后序遍历(仅二叉树)
                指先访问孩子,然后访问根的遍历方式

        4.层次遍历
                一层一层的访问,所以一般用广度优先遍历。

======================================================================================================

树结点 顺序存储结构(tree node sequence)

结点:

        包括一个数据元素及若干个指向其它子树的分支;例如,A,B,C,D等。


在数据结构的图形表示中,对于数据集合中的每一个数据元素用中间标有元素值的方框表示,一般称之为数据结点,简称结点。

        在C语言中,链表中每一个元素称为“结点”,每个结点都应包括两个部分:一为用户需要用的实际数据;二为下一个结点的地址,即指针域和数据域。

        数据结构中的每一个数据结点对应于一个储存单元,这种储存单元称为储存结点,也可简称结点

树结点(树节点):

        《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

树节点相关术语:

  • 节点的度:一个节点含有的子树的个数称为该节点的度;
  • 叶节点或终端节点:度为0的节点称为叶节点;
  • 非终端节点或分支节点:度不为0的节点;
  • 双亲节点或父节点:若一个结点含有子节点,则这个节点称为其子节点的父节点;
  • 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
  • 兄弟节点:具有相同父节点的节点互称为兄弟节点;
  • 节点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
  • 堂兄弟节点:双亲在同一层的节点互为堂兄弟;
  • 节点的祖先:从根到该节点所经分支上的所有节点;
  • 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。

        根据树结点的相关定义,采用“双亲孩子表示法”。其属性如下:

[cpp] 
view plain
copy
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》
《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

  1. 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;   
  2. T                                   m_data;                 //the friend class can use it directly  
  3.   
  4. AL_TreeNodeSeq<T>*                    m_pParent;              //Parent position  
  5. AL_ListSeq<AL_TreeNodeSeq<T>*>      m_listChild;            //All Child tree node  

树的几种表示法

        在实际中,可使用多种形式的存储结构来表示树,既可以采用顺序存储结构,也可以采用链式存储结构,但无论采用何种存储方式,都要求存储结构不但能存储各结点本身的数据信息,还要能唯一地反映树中各结点之间的逻辑关系。

        1.双亲表示法

                由于树中的每个结点都有唯一的一个双亲结点,所以可用一组连续的存储空间(一维数组)存储树中的各个结点,数组中的一个元素表示树中的一个结点,每个结点含两个域,数据域存放结点本身信息,双亲域指示本结点的双亲结点在数组中位置。

                《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

        2.孩子表示法

                1.多重链表:每个结点有多个指针域,分别指向其子树的根
                        1)结点同构:结点的指针个数相等,为树的度k,这样n个结点度为k的树必有n(k-1)+1个空链域.
                                                《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》
                        2)结点不同构:结点指针个数不等,为该结点的度d
                                                《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

                2.孩子链表:每个结点的孩子结点用单链表存储,再用含n个元素的结构数组指向每个孩子链表

                《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

        3.双亲孩子表示法

                1.双亲表示法,PARENT(T,x)可以在常量时间内完成,但是求结点的孩子时需要遍历整个结构。
                2.孩子链表表示法,适于那些涉及孩子的操作,却不适于PARENT(T,x)操作。
                3.将双亲表示法和孩子链表表示法合在一起,可以发挥以上两种存储结构的优势,称为带双亲的孩子链表表示法

                《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

        4.双亲孩子兄弟表示法 (二叉树专用)

                又称为二叉树表示法,以二叉链表作为树的存储结构。

                                《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

                《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

顺序存储结构

        在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构. 

        顺序存储结构是存储结构类型中的一种,该结构是把逻辑上相邻的节点存储在物理位置上相邻的存储单元中,结点之间的逻辑关系由存储单元的邻接关系来体现。由此得到的存储结构为顺序存储结构,通常顺序存储结构是借助于计算机程序设计语言(例如c/c++)的数组来描述的。

        顺序存储结构的主要优点是节省存储空间,因为分配给数据的存储单元全用存放结点的数据(不考虑c/c++语言中数组需指定大小的情况),结点之间的逻辑关系没有占用额外的存储空间。采用这种方法时,可实现对结点的随机存取,即每一个结点对应一个序号,由该序号可以直接计算出来结点的存储地址。但顺序存储方法的主要缺点是不便于修改,对结点的插入、删除运算时,可能要移动一系列的结点。

        优点:

                随机存取表中元素。缺点:插入和删除操作需要移动元素。


        本代码默认list可以容纳的item数目为100个,用户可以自行设置item数目。当list饱和时,由于Tree是非线性结构,动态扩展内存相当麻烦。因此示例中的Demo及代码将不会动态扩展内存

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

以后的笔记潇汀会尽量详细讲解一些相关知识的,希望大家继续关注我的博客。

本节笔记到这里就结束了。 潇汀一有时间就会把自己的学习心得,觉得比较好的知识点写出来和大家一起分享。 编程开发的路很长很长,非常希望能和大家一起交流,共同学习,共同进步。 如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨编程相关的问题。 最后,谢谢你们一直的支持~~~~

       C++完整个代码示例(代码在VS2005下测试可运行)

        《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

《※数据结构※→☆非线性结构(tree)☆============AVL树/自平衡二叉查找树(AVL树/自平衡二叉查) 顺序存储结构(tree AVL sequence)(二十五)》

AL_TreeNodeBinSearchSeq.h

/**
  @(#)$Id: AL_TreeNodeBinSearchSeq.h 99 2013-12-25 02:37:20Z xiaoting $
  @brief	Each of the data structure corresponds to a data node storage unit, this storage unit is called storage node, the node can 
  also be referred to.
	
  The related concepts of tree node 
  1.degree		degree node: A node of the subtree containing the number is called the node degree;
  2.leaf			leaf nodes or terminal nodes: degree 0 are called leaf nodes;
  3.branch		non-terminal node or branch node: node degree is not 0;
  4.parent		parent node or the parent node: If a node contains a child node, this node is called its child node's parent;
  5.child			child node or child node: A node subtree containing the root node is called the node's children;
  6.slibing		sibling nodes: nodes with the same parent node is called mutual sibling;
  7.ancestor		ancestor node: from the root to the node through all the nodes on the branch;
  8.descendant	descendant nodes: a node in the subtree rooted at any node is called the node's descendants.

  ////////////////////////////////Binary Search Tree(Binary Sort Tree)//////////////////////////////////////////
  Binary Search Tree(Binary Sort Tree), also known as a binary search tree, also known as binary search tree. It is either empty 
  tree; or a binary tree with the following properties: (1) If the left subtree is not empty, then all nodes in the left sub-tree, 
  the values ​​are less than the value of its root; (2) if the right subtree is not empty, then all nodes in the right subtree are 
  greater than the value of the value of its root; (3) left and right subtrees are also binary sort tree;

  ////////////////////////////////Binary Tree//////////////////////////////////////////
  In computer science, a binary tree is that each node has at most two sub-trees ordered tree. Usually the root of the subtree is 
  called "left subtree" (left subtree) and the "right subtree" (right subtree). Binary tree is often used as a binary search tree 
  and binary heap or a binary sort tree. Binary tree each node has at most two sub-tree (does not exist a degree greater than two 
  nodes), left and right sub-tree binary tree of the points, the order can not be reversed. Binary i-th layer of at most 2 power 
  nodes i -1; binary tree of depth k at most 2 ^ (k) -1 nodes; for any binary tree T, if it is the terminal nodes (i.e. leaf nodes) 
  is, the nodes of degree 2 is, then = + 1.

  ////////////////////////////////Sequential storage structure//////////////////////////////////////////
  Using a set of addresses in the computer storage unit sequentially stores continuous linear form of individual data elements, called 
  the linear order of the table storage structure.

  Sequential storage structure is a type of a storage structure, the structure is the logically adjacent nodes stored in the physical 
  location of the adjacent memory cells, the logical relationship between nodes from the storage unit to reflect the adjacency. 
  Storage structure thus obtained is stored in order structure, usually by means of sequential storage structure computer programming 
  language (e.g., c / c) of the array to describe.

  The main advantage of the storage structure in order to save storage space, because the allocation to the data storage unit storing 
  all nodes with data (without regard to c / c language in the array size required for the case), the logical relationship between 
  the nodes does not take additional storage space. In this method, the node can be realized on a random access, that is, each node 
  corresponds to a number, the number can be calculated directly from the node out of the memory address. However, the main 
  disadvantage of sequential storage method is easy to modify the node insert, delete operations, may have to move a series of nodes.
          
  Benefits:
	Random Access table elements. 
  Disadvantages: 
    insert and delete operations need to move elements.

  @Author $Author: xiaoting $
  @Date $Date: 2013-12-25 10:37:20 +0800 (周三, 25 十二月 2013) $
  @Revision $Revision: 99 $
  @URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeBinSearchSeq.h $
  @Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeBinSearchSeq.h 99 2013-12-25 02:37:20Z xiaoting $
 */

#ifndef CXX_AL_TREENODEBINSEARCHSEQ_H
#define CXX_AL_TREENODEBINSEARCHSEQ_H

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

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


///////////////////////////////////////////////////////////////////////////
//			AL_TreeNodeBinSearchSeq
///////////////////////////////////////////////////////////////////////////

template<typename T, typename KEY> class AL_TreeBinSearchSeq;
template<typename T, typename KEY> class AL_TreeAVLSeq;

template<typename T, typename KEY> 
class AL_TreeNodeBinSearchSeq
{
friend class AL_TreeBinSearchSeq<T, KEY>;
friend class AL_TreeAVLSeq<T, KEY>;

public:
	/**
	* Destruction
	*
	* @param
	* @return
	* @note
	* @attention 
	*/
	~AL_TreeNodeBinSearchSeq();
	
	/**
	* 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);

	/**
	* GetWeight
	*
	* @param
	* @return	DWORD
	* @note If the tree node is assigned a numerical value has some meaning, then this value is called the node weights
	* @attention only be used in Huffman tree...
	*/
	DWORD GetWeight() const;

	/**
	* SetWeight
	*
	* @param	DWORD dwWeight <IN>
	* @return	
	* @note If the tree node is assigned a numerical value has some meaning, then this value is called the node weights
	* @attention only be used in Huffman tree...
	*/
	VOID SetWeight(DWORD dwWeight);

	/**
	* GetData
	*
	* @param
	* @return	T
	* @note 
	* @attention 
	*/
	T GetData() const;

	/**
	* SetData
	*
	* @param	const T& tData <IN>
	* @return	
	* @note 
	* @attention 
	*/
	VOID SetData(const T& tData);

	/**
	* GetKey
	*
	* @param
	* @return	KEY
	* @note 
	* @attention 
	*/
	KEY GetKey() const;

	/**
	* SetKey
	*
	* @param	const KEY& tKey <IN>
	* @return	
	* @note 
	* @attention 
	*/
	VOID SetKey(const KEY& tKey);

	/**
	* GetParent
	*
	* @param	
	* @return	AL_TreeNodeBinSearchSeq<T, KEY>*	
	* @note parent node pointer, not to manager memory
	* @attention 
	*/
	AL_TreeNodeBinSearchSeq<T, KEY>*	GetParent() const;

	/**
	* SetParent
	*
	* @param	DWORD dwIndex <IN>
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pParent <IN>
	* @return	BOOL
	* @note parent node pointer, not to manager memory
	* @attention as the child to set the parent at the index (from the left of parent's child ) [0x00: left child, 0x01: right child]
	*/
	BOOL SetParent(DWORD dwIndex, AL_TreeNodeBinSearchSeq<T, KEY>* pParent);

	/**
	* SetParentLeft
	*
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* 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_TreeNodeBinSearchSeq<T, KEY>* pParent);

	/**
	* SetParentRight
	*
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* 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_TreeNodeBinSearchSeq<T, KEY>* pParent);

	/**
	* Insert
	*
	* @param	DWORD dwIndex <IN>
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeBinSearchSeq<T, KEY>*  into the child notes at the position [0x00: left child, 0x01: right child]
	* @attention
	*/
	BOOL Insert(DWORD dwIndex, AL_TreeNodeBinSearchSeq<T, KEY>* pInsertChild);

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

	/**
	* InsertRight
	*
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeBinSearchSeq<T, KEY>*  into the child notes at the right
	* @attention
	*/
	BOOL InsertRight(AL_TreeNodeBinSearchSeq<T, KEY>* pInsertChild);
	
	/**
	* RemoveParent
	*
	* @param
	* @return	BOOL
	* @note remove the parent note
	* @attention
	*/
	BOOL RemoveParent();

	/**
	* Remove
	*
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pRemoveChild <IN>
	* @return	BOOL
	* @note remove the notes in the child
	* @attention
	*/
	BOOL Remove(AL_TreeNodeBinSearchSeq<T, KEY>* pRemoveChild);

	/**
	* Remove
	*
	* @param	DWORD dwIndex <IN>
	* @return	BOOL
	* @note remove the child notes at the position [0x00: left child, 0x01: right child]
	* @attention
	*/
	BOOL Remove(DWORD dwIndex);

	/**
	* RemoveLeft
	*
	* @param
	* @return	BOOL
	* @note remove the child notes at the left
	* @attention
	*/
	BOOL RemoveLeft();

	/**
	* RemoveRight
	*
	* @param
	* @return	BOOL
	* @note remove the child notes at the right
	* @attention
	*/
	BOOL RemoveRight();

	/**
	* GetChildLeft
	*
	* @param	
	* @return	AL_TreeNodeBinSearchSeq<T, KEY>*
	* @note 
	* @attention
	*/
	AL_TreeNodeBinSearchSeq<T, KEY>* GetChildLeft() const;

	/**
	* GetChildRight
	*
	* @param	
	* @return	AL_TreeNodeBinSearchSeq<T, KEY>*
	* @note 
	* @attention
	*/
	AL_TreeNodeBinSearchSeq<T, KEY>* 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_TreeNodeBinSearchSeq<T, KEY>* 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_TreeNodeBinSearchSeq<T, KEY>* pChild) const;

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

	/**
	* GetAncestor
	*
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& 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_TreeNodeBinSearchSeq<T, KEY>*>& listAncestor) const;

	/**
	* GetDescendant
	*
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& 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_TreeNodeBinSearchSeq<T, KEY>*>& listDescendant) const;

	/**
	* Clear
	*
	* @param
	* @return	VOID
	* @note
	* @attention 
	*/
	VOID Clear();

protected:
private:

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

	/**
	* Copy Construct
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>& cAL_TreeNodeBinSearchSeq
	* @return
	* @note
	* @attention
	*/
	AL_TreeNodeBinSearchSeq(const AL_TreeNodeBinSearchSeq<T, KEY>& cAL_TreeNodeBinSearchSeq);

	/**
	* Assignment
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>& cAL_TreeNodeBinSearchSeq
	* @return	AL_TreeNodeBinSearchSeq<T, KEY>&
	* @note
	* @attention
	*/
	AL_TreeNodeBinSearchSeq<T, KEY>& operator = (const AL_TreeNodeBinSearchSeq<T, KEY>& cAL_TreeNodeBinSearchSeq);

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;	
	DWORD								m_dwWeight;				//If the tree node is assigned a numerical value has some meaning, then this value is called the node weights
																//only be used in Huffman tree...

	T									m_tData;					//the friend class can use it directly
	KEY									m_tKey;					//the key for binary search (sort)

	AL_TreeNodeBinSearchSeq<T, KEY>*				m_pParent;				//Parent position
	AL_TreeNodeBinSearchSeq<T, KEY>*				m_pChildLeft;			//Child tree node left
	AL_TreeNodeBinSearchSeq<T, KEY>*				m_pChildRight;			//Child tree node right
};

///////////////////////////////////////////////////////////////////////////
//			AL_TreeNodeBinSearchSeq
///////////////////////////////////////////////////////////////////////////

/**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
template<typename T, typename KEY> 
AL_TreeNodeBinSearchSeq<T, KEY>::AL_TreeNodeBinSearchSeq():
m_dwLevel(0x00),
m_dwWeight(0x00),
m_pParent(NULL),
m_pChildLeft(NULL),
m_pChildRight(NULL)
{

}

/**
* Construction
*
* @param	const T& tData <IN>
* @param	const KEY& tKey <IN>
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
template<typename T, typename KEY> 
AL_TreeNodeBinSearchSeq<T, KEY>::AL_TreeNodeBinSearchSeq(const T& tData, const KEY& tKey):
m_dwLevel(0x00),
m_dwWeight(0x00),
m_tData(tData),
m_tKey(tKey),
m_pParent(NULL),
m_pChildLeft(NULL),
m_pChildRight(NULL)
{

}


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

/**
* GetWeight
*
* @param
* @return	DWORD
* @note If the tree node is assigned a numerical value has some meaning, then this value is called the node weights
* @attention only be used in Huffman tree...
*/
template<typename T, typename KEY> DWORD 
AL_TreeNodeBinSearchSeq<T, KEY>::GetWeight() const
{
	return m_dwWeight;
}

/**
* SetWeight
*
* @param	DWORD dwWeight <IN>
* @return	
* @note If the tree node is assigned a numerical value has some meaning, then this value is called the node weights
* @attention only be used in Huffman tree...
*/
template<typename T, typename KEY> VOID 
AL_TreeNodeBinSearchSeq<T, KEY>::SetWeight(DWORD dwWeight)
{
	m_dwWeight = dwWeight;
}

/**
* GetData
*
* @param
* @return	T
* @note 
* @attention 
*/
template<typename T, typename KEY> T 
AL_TreeNodeBinSearchSeq<T, KEY>::GetData() const
{
	return m_tData;
}

/**
* SetData
*
* @param	const T& tData <IN>
* @return	
* @note 
* @attention 
*/
template<typename T, typename KEY> VOID 
AL_TreeNodeBinSearchSeq<T, KEY>::SetData(const T& tData)
{
	m_tData = tData;
}

/**
* GetKey
*
* @param
* @return	KEY
* @note 
* @attention 
*/
template<typename T, typename KEY> KEY 
AL_TreeNodeBinSearchSeq<T, KEY>::GetKey() const
{
	return m_tKey;
}

/**
* SetData
*
* @param	const KEY& tKey <IN>
* @return	
* @note 
* @attention 
*/
template<typename T, typename KEY> VOID 
AL_TreeNodeBinSearchSeq<T, KEY>::SetKey(const KEY& tKey)
{
	m_tKey = tKey;
}

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

/**
* SetParent
*
* @param	DWORD dwIndex <IN>
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pParent <IN>
* @return	BOOL
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the index (from the left of parent's child ) [0x00: left child, 0x01: right child]
*/
template<typename T, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::SetParent(DWORD dwIndex, AL_TreeNodeBinSearchSeq<T, KEY>* pParent)
{
	if (NULL == pParent) {
		return FALSE;
	}

	BOOL bSetParent = FALSE;
	bSetParent = pParent->Insert(dwIndex, this);
	if (TRUE == bSetParent) {
		//current node insert to the parent successfully
		if (NULL != m_pParent) {
			//current node has parent
			if (FALSE == m_pParent->Remove(this)) {
				return FALSE;
			}
		}
		m_pParent = pParent;
	}
	return bSetParent;
}

/**
* SetParentLeft
*
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* 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, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::SetParentLeft(AL_TreeNodeBinSearchSeq<T, KEY>* pParent)
{
	return SetParent(0x00, pParent);
}

/**
* SetParentRight
*
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* 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, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::SetParentRight(AL_TreeNodeBinSearchSeq<T, KEY>* pParent)
{
	return SetParent(0x01, pParent);
}

/**
* Insert
*
* @param	DWORD dwIndex <IN>
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeBinSearchSeq<T, KEY>*  into the child notes at the position [0x00: left child, 0x01: right child]
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::Insert(DWORD dwIndex, AL_TreeNodeBinSearchSeq<T, KEY>* pInsertChild)
{
	if (0x01 < dwIndex || NULL == pInsertChild) {
		return FALSE;
	}
	
	if (this == pInsertChild) {
		//itself
		return FALSE;
	}

	BOOL bInsert = FALSE;
	if (0x00 == dwIndex && NULL == m_pChildLeft) {
		//left and the child left not exist
		m_pChildLeft = pInsertChild;
		bInsert = TRUE;
	}
	else if (0x01 == dwIndex && NULL == m_pChildRight) {
		//right and the child right not exist
		m_pChildRight = pInsertChild;
		bInsert = TRUE;
	}
	else {
		//no case
		bInsert = FALSE;
	}

	if (TRUE == bInsert) {
		if (GetLevel()+1 != pInsertChild->GetLevel()) {
			//deal with the child level
			INT iLevelDiff = pInsertChild->GetLevel() - GetLevel();
			pInsertChild->SetLevel(GetLevel()+1);

			AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listDescendant;
			if (TRUE == pInsertChild->GetDescendant(listDescendant)) {
				//insert child node has descendant
				AL_TreeNodeBinSearchSeq<T, KEY>* pDescendant = NULL;
				for (DWORD dwCnt=0x00; dwCnt<listDescendant.Length(); dwCnt++) {
					if (TRUE == listDescendant.Get(dwCnt, pDescendant)) {
						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_TreeNodeBinSearchSeq<T, KEY>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeBinSearchSeq<T, KEY>*  into the child notes at the left
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::InsertLeft(AL_TreeNodeBinSearchSeq<T, KEY>* pInsertChild)
{
	return Insert(0x00, pInsertChild);
}

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

/**
* RemoveParent
*
* @param
* @return	BOOL
* @note remove the parent note
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::RemoveParent()
{
	//don't care the parent node exist or not
	BOOL bRemove = TRUE;

	if (NULL != m_pParent) {
		bRemove = m_pParent->Remove(this);
		m_pParent = NULL;
	}

	return bRemove;
}

/**
* Remove
*
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pRemoveChild <IN>
* @return	BOOL
* @note remove the notes in the child
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::Remove(AL_TreeNodeBinSearchSeq<T, KEY>* pRemoveChild)
{
	if (NULL == pRemoveChild) {
		//nothing to removed
		return TRUE;
	}

	BOOL bRemove = FALSE;
	if (m_pChildLeft == pRemoveChild) {
		m_pChildLeft = NULL;
		bRemove = TRUE;
	}
	else if (m_pChildRight ==  pRemoveChild) {
		m_pChildRight = NULL;
		bRemove = TRUE;
	}
	else {
		bRemove = FALSE;
	}
	pRemoveChild->m_pParent = NULL;
	return bRemove;
}

/**
* Remove
*
* @param	DWORD dwIndex <IN>
* @return	BOOL
* @note remove the child notes at the position [0x00: left child, 0x01: right child]
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::Remove(DWORD dwIndex)
{
	AL_TreeNodeBinSearchSeq<T, KEY>* pRemoveChild = NULL;
	if (0x00 == dwIndex) {
		pRemoveChild = m_pChildLeft;
	}
	else if (0x01 == dwIndex) {
		pRemoveChild = m_pChildRight;
	}
	else {
		return FALSE;
	}

	return Remove(pRemoveChild);
}

/**
* RemoveLeft
*
* @param
* @return	BOOL
* @note remove the child notes at the left
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::RemoveLeft()
{
	return Remove(m_pChildLeft);
}

/**
* RemoveRight
*
* @param
* @return	BOOL
* @note remove the child notes at the right
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::RemoveRight()
{
	return Remove(m_pChildRight);
}

/**
* GetChildLeft
*
* @param	
* @return	AL_TreeNodeBinSearchSeq<T, KEY>*
* @note 
* @attention
*/
template<typename T, typename KEY> AL_TreeNodeBinSearchSeq<T, KEY>* 
AL_TreeNodeBinSearchSeq<T, KEY>::GetChildLeft() const
{
	return m_pChildLeft;
}

/**
* GetChildRight
*
* @param	
* @return	AL_TreeNodeBinSearchSeq<T, KEY>*
* @note 
* @attention
*/
template<typename T, typename KEY> AL_TreeNodeBinSearchSeq<T, KEY>* 
AL_TreeNodeBinSearchSeq<T, KEY>::GetChildRight() const
{
	return m_pChildRight;
}

/**
* GetDegree
*
* @param
* @return	DWORD
* @note degree node: A node of the subtree containing the number is called the node degree;
* @attention 
*/
template<typename T, typename KEY> DWORD 
AL_TreeNodeBinSearchSeq<T, KEY>::GetDegree() const
{
	DWORD dwDegree = 0x00;
	if (NULL != m_pChildLeft) {
		dwDegree++;
	}
	if (NULL != m_pChildRight) {
		dwDegree++;
	}

	return dwDegree;
}

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

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

	listSibling.Clear();

	AL_TreeNodeBinSearchSeq<T, KEY>* pParentChild = GetChildLeft();
	if (NULL != pParentChild) {
		if (pParentChild != this) {
			//not itself
			listSibling.InsertEnd(pParentChild);
			bSibling = TRUE;
		}
	}

	pParentChild = GetChildRight();
	if (NULL != pParentChild) {
		if (pParentChild != this) {
			//not itself
			listSibling.InsertEnd(pParentChild);
			bSibling = TRUE;
		}
	}

	return bSibling;
}

/**
* GetAncestor
*
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listAncestor <OUT>
* @return	BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention 
*/
template<typename T, typename KEY> BOOL
AL_TreeNodeBinSearchSeq<T, KEY>::GetAncestor(AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listAncestor) const
{
	if (NULL == m_pParent) {
		//not parent node
		return FALSE;
	}

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

/**
* GetDescendant
*
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listDescendant <OUT>
* @return	BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention 
*/
template<typename T, typename KEY> BOOL 
AL_TreeNodeBinSearchSeq<T, KEY>::GetDescendant(AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listDescendant) const
{
	listDescendant.Clear();
	if (TRUE == IsLeaf()) {
		//child node, No Descendant
		return TRUE;
	}

	AL_TreeNodeBinSearchSeq<T, KEY>* pDescendant = GetChildLeft();
	if (NULL != pDescendant) {
		listDescendant.InsertEnd(pDescendant);
	}

	pDescendant = GetChildRight();
	if (NULL != pDescendant) {
		listDescendant.InsertEnd(pDescendant);
	}

	//loop the all node in listDescendant
	DWORD dwDescendantLoop = 0x00;
	AL_TreeNodeBinSearchSeq<T, KEY>* pDescendantLoop = NULL;
	while (TRUE == listDescendant.Get(dwDescendantLoop, pDescendant)) {
		dwDescendantLoop++;
		if (NULL != pDescendant) {
			pDescendantLoop = pDescendant->GetChildLeft();
			if (NULL != pDescendantLoop) {
				listDescendant.InsertEnd(pDescendantLoop);
			}

			pDescendantLoop = pDescendant->GetChildRight();
			if (NULL != pDescendantLoop) {
				listDescendant.InsertEnd(pDescendantLoop);
			}
		}
		else {
			//error
			return FALSE;
		}
	}
	return TRUE;
}

/**
* Clear
*
* @param
* @return	VOID
* @note
* @attention 
*/
template<typename T, typename KEY> VOID 
AL_TreeNodeBinSearchSeq<T, KEY>::Clear()
{
	m_dwLevel = 0x00;
	m_dwWeight = 0x00;
	m_pParent = NULL;
	m_pChildLeft = NULL;
	m_pChildRight = NULL;
}

/**
* Assignment
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>& cAL_TreeNodeBinSearchSeq
* @return	AL_TreeNodeBinSearchSeq<T, KEY>&
* @note
* @attention
*/
template<typename T, typename KEY> AL_TreeNodeBinSearchSeq<T, KEY>& 
AL_TreeNodeBinSearchSeq<T, KEY>::operator = (const AL_TreeNodeBinSearchSeq<T, KEY>& cAL_TreeNodeBinSearchSeq)
{
	m_dwLevel = cAL_TreeNodeBinSearchSeq.m_dwLevel;
	m_dwWeight = cAL_TreeNodeBinSearchSeq.m_dwWeight;
	m_tData = cAL_TreeNodeBinSearchSeq.m_tData;
	m_tKey = cAL_TreeNodeBinSearchSeq.m_tKey;
	m_pParent = cAL_TreeNodeBinSearchSeq.m_pParent;
	m_pChildLeft = cAL_TreeNodeBinSearchSeq.m_pChildLeft;
	m_pChildRight = cAL_TreeNodeBinSearchSeq.m_pChildRight;
	return *this;
}
#endif // CXX_AL_TREENODEBINSEARCHSEQ_H
/* EOF */

AL_TreeAVLSeq.h

/**
  @(#)$Id: AL_TreeAVLSeq.h 100 2013-12-25 02:41:58Z 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.

  ////////////////////////////////AVL Tree//////////////////////////////////////////
  In computer science, AVL tree is a self-balancing binary search tree first invented. AVL tree height in the maximum difference of 
  any two nodes in the tree as a child, so it is also called height-balanced tree. Search, insert, and delete are O (log n) in the 
  average and worst case. Additions and deletions may be required by one or more trees to re-balance the rotating tree. AVL tree is 
  named after its inventor GM Adelson-Velsky and EM Landis, they published it in the 1962 paper "An algorithm for the organization 
  of information" in.

  Balance factor node is the height of its left subtree minus the height of its right subtree (sometimes opposite). Node with a 
  balance factor 0, or -1 is considered balanced. Node with balance factor -2 or 2 is considered unbalanced and requires 
  re-balancing the tree. Balance factor can be directly stored in each node, or may be stored in a node from the subtree height 
  calculated.

  ////////////////////////////////Binary Search Tree(Binary Sort Tree)//////////////////////////////////////////
  Binary Search Tree(Binary Sort Tree), also known as a binary search tree, also known as binary search tree. It is either empty 
  tree; or a binary tree with the following properties: 
  (1) If the left subtree is not empty, then all nodes in the left sub-tree, the values ​​are less than the value of its root; 
  (2) if the right subtree is not empty, then all nodes in the right subtree are greater than the value of the value of its root; 
  (3) left and right subtrees are also binary sort tree;

  ////////////////////////////////Binary Tree//////////////////////////////////////////
  In computer science, a binary tree is that each node has at most two sub-trees ordered tree. Usually the root of the subtree is 
  called "left subtree" (left subtree) and the "right subtree" (right subtree). Binary tree is often used as a binary search tree 
  and binary heap or a binary sort tree. Binary tree each node has at most two sub-tree (does not exist a degree greater than two 
  nodes), left and right sub-tree binary tree of the points, the order can not be reversed. Binary i-th layer of at most 2 power 
  nodes i -1; binary tree of depth k at most 2 ^ (k) -1 nodes; for any binary tree T, if it is the terminal nodes (i.e. leaf nodes) 
  is, the nodes of degree 2 is, then = + 1.

  ////////////////////////////////Complete Binary Tree//////////////////////////////////////////
  If set binary height of h, the h layer in addition, the other layers (1 ~ h-1) has reached the maximum number of nodes, right to 
  left, the h-layer node number of consecutive missing, this is a complete binary tree .

  ////////////////////////////////Full Binary Tree//////////////////////////////////////////
  A binary tree of height h is 2 ^ h-1 element is called a full binary tree.

  ////////////////////////////////Sequential storage structure//////////////////////////////////////////
  Using a set of addresses in the computer storage unit sequentially stores continuous linear form of individual data elements, called 
  the linear order of the table storage structure.

  Sequential storage structure is a type of a storage structure, the structure is the logically adjacent nodes stored in the physical 
  location of the adjacent memory cells, the logical relationship between nodes from the storage unit to reflect the adjacency. 
  Storage structure thus obtained is stored in order structure, usually by means of sequential storage structure computer programming 
  language (e.g., c / c) of the array to describe.

  The main advantage of the storage structure in order to save storage space, because the allocation to the data storage unit storing 
  all nodes with data (without regard to c / c language in the array size required for the case), the logical relationship between 
  the nodes does not take additional storage space. In this method, the node can be realized on a random access, that is, each node 
  corresponds to a number, the number can be calculated directly from the node out of the memory address. However, the main 
  disadvantage of sequential storage method is easy to modify the node insert, delete operations, may have to move a series of nodes.
          
  Benefits:
	Random Access table elements. 
  Disadvantages: 
    insert and delete operations need to move elements.

  @Author $Author: xiaoting $
  @Date $Date: 2013-12-25 10:41:58 +0800 (周三, 25 十二月 2013) $
  @Revision $Revision: 100 $
  @URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeAVLSeq.h $
  @Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeAVLSeq.h 100 2013-12-25 02:41:58Z xiaoting $
 */

#ifndef CXX_AL_TREEAVLSEQ_H
#define CXX_AL_TREEAVLSEQ_H

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

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

#ifndef CXX_AL_TREENODEAVLSEQ_H
#include "AL_TreeNodeBinSearchSeq.h"
#endif

#ifndef CXX_AL_STACKSEQ_H
#include "AL_StackSeq.h"
#endif

///////////////////////////////////////////////////////////////////////////
//			AL_TreeAVLSeq
///////////////////////////////////////////////////////////////////////////

template<typename T, typename KEY> 
class AL_TreeAVLSeq
{
public:
	static const DWORD TREEAVLSEQ_DEFAULTSIZE			= 100;
	static const DWORD TREEAVLSEQ_MAXSIZE				= 0xffffffff;
	static const DWORD TREEAVLSEQ_HEIGHTINVALID			= 0xffffffff;

	/**
	* Construction
	*
	* @param	DWORD dwSize (default value: TREEAVLSEQ_DEFAULTSIZE)
	* @return
	* @note
	* @attention
	*/
	AL_TreeAVLSeq(DWORD dwSize = TREEAVLSEQ_DEFAULTSIZE);

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

	/**
	* IsEmpty
	*
	* @param VOID
	* @return BOOL
	* @note the tree has data?
	* @attention
	*/
	BOOL IsEmpty() const;
	
	/**
	* GetRootNode
	*
	* @param
	* @return	const AL_TreeNodeBinSearchSeq<T, KEY>*
	* @note Get the root data
	* @attention 
	*/
	const AL_TreeNodeBinSearchSeq<T, KEY>* GetRootNode() const;

	/**
	* GetDegree
	*
	* @param
	* @return	DWORD
	* @note Degree of tree: a tree, the maximum degree of the node of the tree is called degree;
	* @attention 
	*/
	DWORD GetDegree() const;


	/**
	* GetHeight
	*
	* @param	
	* @return	DWORD
	* @note Height or depth of the tree: the maximum level of nodes in the tree;
	* @attention 
	*/
	DWORD GetHeight() const;

	/**
	* GetNodesNum
	*
	* @param
	* @return	DWORD
	* @note get the notes number of the tree 
	* @attention 
	*/
	DWORD GetNodesNum() const;

	/**
	* Clear
	*
	* @param
	* @return	
	* @note 
	* @attention 
	*/
	VOID Clear();

	/**
	* PreOrderTraversal
	*
	* @param	AL_ListSeq<T>& listOrder <OUT>
	* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
	* @return	BOOL
	* @note Pre-order traversal
	* @attention 
	*/
	BOOL PreOrderTraversal(AL_ListSeq<T>& listOrder, AL_ListSeq<KEY>& listKey = AL_ListSeq<KEY>()) const;

	/**
	* InOrderTraversal
	*
	* @param	AL_ListSeq<T>& listOrder <OUT>
	* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
	* @return	BOOL
	* @note In-order traversal
	* @attention 
	*/
	BOOL InOrderTraversal(AL_ListSeq<T>& listOrder, AL_ListSeq<KEY>& listKey = AL_ListSeq<KEY>()) const;

	/**
	* PostOrderTraversal
	*
	* @param	AL_ListSeq<T>& listOrder <OUT>
	* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
	* @return	BOOL
	* @note Post-order traversal
	* @attention 
	*/
	BOOL PostOrderTraversal(AL_ListSeq<T>& listOrder, AL_ListSeq<KEY>& listKey = AL_ListSeq<KEY>()) const;

	/**
	* LevelOrderTraversal
	*
	* @param	AL_ListSeq<T>& listOrder <OUT>
	* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
	* @return	BOOL
	* @note Level-order traversal
	* @attention 
	*/
	BOOL LevelOrderTraversal(AL_ListSeq<T>& listOrder, AL_ListSeq<KEY>& listKey = AL_ListSeq<KEY>()) const;

	/**
	* GetSiblingAtNode
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<T>& listSibling <OUT>
	* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
	* @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(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<T>& listSibling, AL_ListSeq<KEY>& listKey = AL_ListSeq<KEY>()) const;

	/**
	* GetAncestorAtNode
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<T>& listAncestor <OUT>
	* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
	* @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(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<T>& listAncestor, AL_ListSeq<KEY>& listKey = AL_ListSeq<KEY>()) const;

	/**
	* GetDescendantAtNode
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<T>& listDescendant <OUT>
	* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
	* @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(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<T>& listDescendant, AL_ListSeq<KEY>& listKey = AL_ListSeq<KEY>()) const;
	
	/**
	* Get
	*
	* @param	const KEY& tKey <IN> 
	* @param	const T& tData <OUT> 
	* @return	BOOL
	* @note
	* @attention
	*/
	BOOL Get(const KEY& tKey, T& tData);

	/**
	* Insert
	*
	* @param	const T& tData <IN> 
	* @param	const KEY& tKey <IN> 
	* @return	BOOL
	* @note
	* @attention
	*/
	BOOL Insert(const T& tData, const KEY& tKey);
	
	/**
	* RemoveNode
	*
	* @param	const KEY& tKey <IN>
	* @return	BOOL
	* @note 
	* @attention  the current tree node must be in the tree, only remove current node and not include it's descendant note
	*/
	BOOL RemoveNode(const KEY& tKey);


	/**
	* Remove
	*
	* @param	const KEY& tKey <IN>
	* @return	BOOL
	* @note 
	* @attention  the current tree node must be in the tree, only remove current node and include it's descendant note
	*/
	BOOL Remove(const KEY& tKey);

	/**
	* IsCompleteTreeBin
	*
	* @param
	* @return	BOOL
	* @note Is Complete Binary Tree
	* @attention If set binary height of h, the h layer in addition, the other layers (1 ~ h-1) has reached the maximum number of 
	             nodes, right to left, the h-layer node number of consecutive missing, this is a complete binary tree .
	*/
	BOOL IsCompleteTreeBin() const;

	/**
	* IsFullTreeBin
	*
	* @param
	* @return	BOOL
	* @note Is Full Binary Tree
	* @attention A binary tree of height h is 2 ^ h-1 element is called a full binary tree.
	*/
	BOOL IsFullTreeBin() const;

	/**
	* IsBalancedTreeBin
	*
	* @param
	* @return	BOOL
	* @note Is Balanced Binary Tree
	* @attention 1). It is an empty tree or the left and right subtrees of its height difference absolute value is not more than 1,
	             2). left and right subtrees are a balanced binary tree.
	*/
	BOOL IsBalancedTreeBin() const;

	//////////////////////////////////////////////////////////////////////////
	/**
	* Print
	*
	* @param
	* @return	VOID
	* @note only for print tree to console (temp)
	* @attention #include <iostream> using namespace std will be include in "stdafx.h"
	*/
	VOID Print() const
	{
		ofstream ofOutput;
		ofOutput.open("Debug\\Tree.txt");
		if (FALSE == ofOutput.is_open()) {
			return;
		}
		
		if (TRUE == IsEmpty()) {
			ofOutput<<"The tree is empty!";
			ofOutput.close();
			return;
		}
		ofOutput<<"Tree Info:";

		AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listTreeNode;
		AL_ListSeq<DWORD> listTable;
		AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listOrder;
		AL_TreeNodeBinSearchSeq<T, KEY>* pTreeNode = NULL;

		if (FALSE == LevelOrderTraversal(m_pRootNode, listOrder)) {
			ofOutput.close();
			return;
		}

		WORD wCnt = 0x00;
		DWORD dwLevel = 0xffffffff;
		DWORD dwTableCnt = 0x00;
		DWORD dwTableInterval = 0x00;
		DWORD dwParentTableCnt = 0x00;
		DWORD dwCurrentTableCnt = 0x00;
		AL_TreeNodeBinSearchSeq<T, KEY>* pParentTreeNode = NULL;
		for (WORD wListOrderCnt = 0x00; wListOrderCnt < listOrder.Length(); wListOrderCnt++) {
			if (FALSE == listOrder.Get(wListOrderCnt, pTreeNode)) {
				ofOutput.close();
				return;
			}
			if (NULL == pTreeNode) {
				ofOutput.close();
				return;
			}

			//set position
			//new line
			bool bNewline = FALSE;
			if (dwLevel != pTreeNode->GetLevel()) {
				ofOutput<<endl;
				bNewline = TRUE;
				dwLevel = pTreeNode->GetLevel();
				dwTableInterval /= 2;
				dwCurrentTableCnt = 0x00;
			}

			if (m_pRootNode == pTreeNode) {
				DWORD dwMax = 0x01;
				for (DWORD dwCntMax=0x00; dwCntMax<GetHeight(); dwCntMax++) {
					dwMax *= 2;
				}
				dwTableCnt = dwMax;
				dwTableInterval = dwMax;
			}
			else {
				pParentTreeNode = pTreeNode->GetParent();
				if (FALSE == listTable.Get(listTreeNode.Find(pParentTreeNode), dwParentTableCnt)) {
					ofOutput.close();
					return;
				}
				if (pTreeNode == pParentTreeNode->GetChildLeft()) {
					dwTableCnt = dwParentTableCnt - dwTableInterval;
				}
				if (pTreeNode == pParentTreeNode->GetChildRight()) {
					dwTableCnt = dwParentTableCnt + dwTableInterval;
				}
			}
			listTreeNode.InsertEnd(pTreeNode);
			listTable.InsertEnd(dwTableCnt);
			//new line
			if (TRUE == bNewline) {
				bNewline = FALSE;
				for (wCnt = 0x00; wCnt < dwTableCnt; wCnt++) {
					ofOutput<<"  ";
					dwCurrentTableCnt++;
				}
			}
			else {
				DWORD dwLoop = dwTableCnt-dwCurrentTableCnt;
				if (dwLoop > 98789){
					ofOutput<<endl;
					ofOutput.close();
					return;
					int xxx =  0;
				}
				for (wCnt = 0x00; wCnt < dwLoop; wCnt++) {
					ofOutput<<"  ";
					dwCurrentTableCnt++;
				}			
			}

			//print data
//			ofOutput<<"↙"<<setfill('0')<<setw(3)<<pTreeNode->GetKey()<<"↘";
			ofOutput<<setfill('0')<<setw(2)<<pTreeNode->GetKey();
			dwCurrentTableCnt++;
		}
		ofOutput<<endl;
		ofOutput.close();
	}

	//////////////////////////////////////////////////////////////////////////
protected:
public:

	/**
	* GetChildNodeLeftAtNode
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @return	const AL_TreeNodeBinSearchSeq<T, KEY>*
	* @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_TreeNodeBinSearchSeq<T, KEY>* GetChildNodeLeftAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const;

	/**
	* GetChildNodeRightAtNode
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @return	const AL_TreeNodeBinSearchSeq<T, KEY>*
	* @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_TreeNodeBinSearchSeq<T, KEY>*  GetChildNodeRightAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const;

	/**
	* GetNode
	*
	* @param	const KEY& tKey <IN> 
	* @return	const AL_TreeNodeBinSearchSeq<T, KEY>* 
	* @note
	* @attention
	*/
	const AL_TreeNodeBinSearchSeq<T, KEY>* GetNode(const KEY& tKey);

	/**
	* GetNode
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
	* @param	const KEY& tKey <IN> 
	* @return	const AL_TreeNodeBinSearchSeq<T, KEY>* 
	* @note		for Recursion search
	* @attention
	*/
	const AL_TreeNodeBinSearchSeq<T, KEY>* GetNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, const KEY& tKey);

	/**
	* Insert
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pRecursionNode <IN> 
	* @param	const T& tData <IN> 
	* @param	const KEY& tKey <IN> 
	* @return	BOOL
	* @note		for Recursion Insert
	* @attention if pRecursionNode may be NULL
	*/
	BOOL Insert(const AL_TreeNodeBinSearchSeq<T, KEY>* pRecursionNode, const T& tData, const KEY& tKey);

	/**
	* InsertLeftAtNode
	*
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	const T& tData <IN> 
	* @param	const KEY& tKey <IN> 
	* @return	BOOL
	* @note insert the tData 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_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, const T& tData, const KEY& tKey);

	/**
	* InsertRightAtNode
	*
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	const T& tData <IN> 
	* @param	const KEY& tKey <IN> 
	* @return	BOOL
	* @note insert the tData 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_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, const T& tData, const KEY& tKey);

	/**
	* InsertAtNode
	*
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
	* @param	DWORD dwIndex <IN>
	* @param	const T& tData <IN>
	* @param	const KEY& tKey <IN> 
	* @return	BOOL
	* @note insert the tData 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_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, DWORD dwIndex, const T& tData, const KEY& tKey);

	/**
	* SelfBalancing
	*
	* @param AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
	* @return	BOOL
	* @note By rotating unbalanced node to make re-balanced binary tree, and find, insert and delete operations time complexity is 
			O (log n) in the average and worst-case
	* @attention AVL tree rotation , a total of four cases, note that all cases are rotated around so that the first node in a 
				binary tree imbalance expanded .
				1. LL type
					Left child of a balanced binary tree left child node to insert a new node , so that the node is no longer 
					balanced . At this time need only to rotate the tree to the right , as shown, the original left child A 
					becomes the parent node B , A becomes the right child and the right subtree of the original B to the left 
					sub A tree , note after the rotation Brh is ( forget the a solid line between Brh marked on the map ) A left 
					subtree
				2. RR type
					The right of a child's balanced binary tree right child nodes insert a new node , so that the node is no longer 
					balanced . Then just put the tree once rotated to the left , as shown in Figure A former right child becomes 
					the parent node B , A becomes its left child , and the original left subtree Blh B becomes A right subtree.
				3. LR type
					Left child of the right child nodes of a balanced binary tree, a new node is inserted so that the node is no 
					longer balanced . At this time needs to be rotated twice, only once the rotation is balanced binary tree can 
					not make again . As shown, a Node B , after the rotation , in the binary tree node A can not maintain a balance 
					in accordance with still left RR type , then the need to rotate once again to the right.
				4. RL type
					The right of a child's balanced binary tree left child node to insert a new node , so that the node is no 
					longer balanced . Similarly , when the need to rotate the two , opposite the direction of rotation with the 
					LR model .
	*/
	BOOL SelfBalancing(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode);

	/**
	* SelfBalancing
	*
	* @param AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
	* @return	BOOL
	* @note By rotating unbalanced node to make re-balanced binary tree, and find, insert and delete operations time complexity is 
			O (log n) in the average and worst-case
	* @attention
	*/
	BOOL RotateLeft(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode);

	/**
	* RotateRight
	*
	* @param AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
	* @return	BOOL
	* @note By rotating unbalanced node to make re-balanced binary tree, and find, insert and delete operations time complexity is 
			O (log n) in the average and worst-case
	* @attention
	*/
	BOOL RotateRight(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode);
	
	/**
	* GetRotateNode
	*
	* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
	* @return const AL_TreeNodeBinSearchSeq<T, KEY>*
				1. NULL: a abnormal case, NULL will be returned
				2. RootNode: can not find rotate node, RootNode will be returned
				3. Other Node: find rotate node, Other Node will be returned
			* @note To back from inserted up to the root node to find a minimal loss of balance tree root pointer
	* @attention if there is no rotate tree node, RootNode will be returned
	*/
	const AL_TreeNodeBinSearchSeq<T, KEY>* GetRotateNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const;

	/**
	* RemoveNode
	*
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @return	BOOL
	* @note 
	* @attention  the current tree node must be in the tree, only remove current node and not include it's descendant note
	1). p a leaf node, just delete the node, and then modify its parent node pointer (note points is the root node and not 
	the root);
	2). p for the single node (ie, only the left subtree or right subtree). Let p and p subtree connected to the node's father, 
	then delete p; (note points is the root node and not the root);
	3). p left subtree and right subtree are not empty. Find p's successor y, because y certainly no left subtree, so you can 
	delete y, and let y father node becomes y's right subtree father node, and use the value of y instead of p values​​; or 
	method two is to find p precursor x, x certainly no right subtree, so you can delete x, and let x, y father node becomes 
	the father of the left subtree of the node;
	*/
	BOOL RemoveNode(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode);

	/**
	* Remove
	*
	* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @return	BOOL
	* @note 
	* @attention  the current tree node must be in the tree, remove current node and include it's descendant note
	*/
	BOOL Remove(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode);

	/**
	* PreOrderTraversal
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
	* @return	BOOL
	* @note Pre-order traversal
	* @attention
	*/
	BOOL PreOrderTraversal(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const;

	/**
	* InOrderTraversal
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
	* @return	BOOL
	* @note In-order traversal
	* @attention
	*/
	BOOL InOrderTraversal(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const;

	/**
	* PostOrderTraversal
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
	* @return	BOOL
	* @note Post-order traversal
	* @attention
	*/
	BOOL PostOrderTraversal(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const;

	/**
	* LevelOrderTraversal
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
	* @return	BOOL
	* @note Level-order traversal
	* @attention 
	*/
	BOOL LevelOrderTraversal(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const;

	/**
	* PreOrderTraversalRecursion
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
	* @return	BOOL
	* @note Pre-order traversal
	* @attention Recursion Traversal
	*/
	BOOL PreOrderTraversalRecursion(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const;

	/**
	* InOrderTraversalRecursion
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
	* @return	BOOL
	* @note In-order traversal
	* @attention Recursion Traversal
	*/
	BOOL InOrderTraversalRecursion(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const;

	/**
	* PostOrderTraversalRecursion
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
	* @return	BOOL
	* @note Post-order traversal
	* @attention Recursion Traversal
	*/
	BOOL PostOrderTraversalRecursion(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const;
	
	/**
	* IsBalancedTreeBinRecursion
	*
	* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @return	BOOL
	* @note Is Balanced Binary Tree
	* @attention 1). It is an empty tree or the left and right subtrees of its height difference absolute value is not more than 1,
	             2). left and right subtrees are a balanced binary tree.
	*/
	BOOL IsBalancedTreeBinRecursion(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const; 

	/**
	* IsBalancedNode
	*
	* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @return	BOOL
	* @note Is Balanced Node
	* @attention the left and right subtrees of its height difference absolute value is not more than 1
	*/
	BOOL IsBalancedNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const; 

	/**
	* GetSiblingAtNode
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listSibling <OUT>
	* @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(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listSibling) const;

	/**
	* GetAncestorAtNode
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listAncestor <OUT>
	* @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(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listAncestor) const;

	/**
	* GetDescendantAtNode
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listDescendant <OUT>
	* @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(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listDescendant) const;
	
	/**
	* RecalcDegreeHeight
	*
	* @param	
	* @return	BOOL
	* @note recalculate Degree Height
	* @attention 
	*/
	BOOL RecalcDegreeHeight();

	/**
	* CalcDegree
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @return	DWORD
	* @note calculate degree form current tree node
	* @attention 
	*/
	DWORD CalcDegree(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const;

	/**
	* CalcHeight
	*
	* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
	* @return	DWORD
	* @note calculate height form current tree node
	* @attention 
	*/
	DWORD CalcHeight(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const;

	/**
	* GetListDataFormListNode
	*
	* @param	
	* @param	const AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listNode <IN>
	* @param	AL_ListSeq<T>& listData <OUT>
	* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
	* @note
	* @attention 
	*/
	BOOL GetListDataFormListNode(const AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listNode, AL_ListSeq<T>& listData, AL_ListSeq<KEY>& listKey = AL_ListSeq<KEY>()) const;

	/**
	* GetPrecursor
	*
	* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
	* @param AL_TreeNodeBinSearchSeq<T, KEY>* pQuotePrecursor <OUT>
	* @return BOOL
	* @note Get Precursor of the current tree node
	* @attention Recursion Search
	*/
	BOOL GetPrecursor(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_TreeNodeBinSearchSeq<T, KEY>*& pQuotePrecursor);

	/**
	* GetSuccessor
	*
	* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
	* @param AL_TreeNodeBinSearchSeq<T, KEY>*& pQuoteSuccessor <OUT>
	* @return BOOL
	* @note Get Successor of the current tree node
	* @attention Recursion Search
	*/
	BOOL GetSuccessor(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_TreeNodeBinSearchSeq<T, KEY>*& pQuoteSuccessor);

	/**
	* 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_TreeAVLSeq<T, KEY>& cAL_TreeAVLSeq
	* @return
	* @note
	* @attention
	*/
	AL_TreeAVLSeq(const AL_TreeAVLSeq<T, KEY>& cAL_TreeAVLSeq);

	/**
	* Assignment
	*
	* @param	const AL_TreeAVLSeq<T, KEY>& cAL_TreeAVLSeq
	* @return	AL_TreeAVLSeq<T, KEY>&
	* @note
	* @attention
	*/
	AL_TreeAVLSeq<T, KEY>& operator = (const AL_TreeAVLSeq<T, KEY>& cAL_TreeAVLSeq);

public:
protected:
private:
	AL_TreeNodeBinSearchSeq<T, KEY>*				m_pTreeNode;			
	DWORD								m_dwMaxSize;
	DWORD								m_dwUsed;

	DWORD								m_dwDegree;
	DWORD								m_dwHeight;
	DWORD								m_dwNumNodes;
	AL_TreeNodeBinSearchSeq<T, KEY>*	m_pRootNode;
};

///////////////////////////////////////////////////////////////////////////
//			AL_TreeAVLSeq
///////////////////////////////////////////////////////////////////////////

/**
* Construction
*
* @param	DWORD dwSize (default value: TREEAVLSEQ_DEFAULTSIZE)
* @return
* @note
* @attention
*/
template<typename T, typename KEY> 
AL_TreeAVLSeq<T, KEY>::AL_TreeAVLSeq(DWORD dwSize):
m_pTreeNode(NULL),
m_dwMaxSize(dwSize),
m_dwUsed(0x00),
m_dwDegree(0x00),
m_dwHeight(TREEAVLSEQ_HEIGHTINVALID),
m_dwNumNodes(0x00),
m_pRootNode(NULL)
{
	if (0x00 == m_dwMaxSize) {
		//for memory deal
		m_dwMaxSize = 1;
	}
	GetBuffer();
}

/**
* Destruction
*
* @param
* @return
* @note
* @attention 
*/
template<typename T, typename KEY> 
AL_TreeAVLSeq<T, KEY>::~AL_TreeAVLSeq()
{
	if (NULL != m_pTreeNode) {
		delete[] m_pTreeNode;
		m_pTreeNode = NULL;
	}
	m_dwMaxSize = 0x00;
	Clear();
}

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

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

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

/**
* Clear
*
* @param
* @return	
* @note 
* @attention 
*/
template<typename T, typename KEY> VOID 
AL_TreeAVLSeq<T, KEY>::Clear()
{
	m_dwUsed = 0x00;
	m_dwDegree = 0x00;
	m_dwHeight = TREEAVLSEQ_HEIGHTINVALID;
	m_dwNumNodes = 0x00;
	m_pRootNode = NULL;
}

/**
* PreOrderTraversal
*
* @param	AL_ListSeq<T>& listOrder <OUT>
* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
* @return	BOOL
* @note Pre-order traversal
* @attention 
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::PreOrderTraversal(AL_ListSeq<T>& listOrder, AL_ListSeq<KEY>& listKey) const
{
	if (NULL == m_pRootNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listNode;
	if (TRUE == PreOrderTraversal(m_pRootNode, listNode)) {
		listOrder.Clear();
		return GetListDataFormListNode(listNode, listOrder, listKey);
	}

	return FALSE;
}

/**
* InOrderTraversal
*
* @param	AL_ListSeq<T>& listOrder <OUT>
* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
* @return	BOOL
* @note In-order traversal
* @attention 
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::InOrderTraversal(AL_ListSeq<T>& listOrder, AL_ListSeq<KEY>& listKey) const
{
	if (NULL == m_pRootNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listNode;
	if (TRUE == InOrderTraversal(m_pRootNode, listNode)) {
		listOrder.Clear();
		return GetListDataFormListNode(listNode, listOrder, listKey);
	}

	return FALSE;
}

/**
* PostOrderTraversal
*
* @param	AL_ListSeq<T>& listOrder <OUT>
* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
* @return	BOOL
* @note Post-order traversal
* @attention 
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::PostOrderTraversal(AL_ListSeq<T>& listOrder, AL_ListSeq<KEY>& listKey) const
{
	if (NULL == m_pRootNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listNode;
	if (TRUE == PostOrderTraversal(m_pRootNode, listNode)) {
		listOrder.Clear();
		return GetListDataFormListNode(listNode, listOrder, listKey);
	}

	return FALSE;
}

/**
* LevelOrderTraversal
*
* @param	AL_ListSeq<T>& listOrder <OUT>
* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
* @return	BOOL
* @note Level-order traversal
* @attention 
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::LevelOrderTraversal(AL_ListSeq<T>& listOrder, AL_ListSeq<KEY>& listKey) const
{
	if (NULL == m_pRootNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listNode;
	if (TRUE == LevelOrderTraversal(m_pRootNode, listNode)) {
		listOrder.Clear();
		return GetListDataFormListNode(listNode, listOrder, listKey);
	}

	return FALSE;
}

/**
* GetSiblingAtNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<T>& listSibling <OUT>
* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
* @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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::GetSiblingAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<T>& listSibling, AL_ListSeq<KEY>& listKey) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listNode;
	if (TRUE == GetSiblingAtNode(pCurTreeNode, listNode)) {
		listSibling.Clear();
		return GetListDataFormListNode(listNode, listSibling, listKey);
	}

	return FALSE;
}

/**
* GetAncestorAtNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<T>& listAncestor <OUT>
* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
* @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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::GetAncestorAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<T>& listAncestor, AL_ListSeq<KEY>& listKey) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listNode;
	if (TRUE == GetAncestorAtNode(pCurTreeNode, listNode)) {
		listAncestor.Clear();
		return GetListDataFormListNode(listNode, listAncestor, listKey);
	}

	return FALSE;
}

/**
* GetDescendantAtNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<T>& listDescendant <OUT>
* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
* @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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::GetDescendantAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<T>& listDescendant, AL_ListSeq<KEY>& listKey) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listNode;
	if (TRUE == GetDescendantAtNode(pCurTreeNode, listNode)) {
		listDescendant.Clear();
		return GetListDataFormListNode(listNode, listDescendant, listKey);
	}

	return FALSE;
}

/**
* Get
*
* @param	const KEY& tKey <IN> 
* @param	const T& tData <OUT> 
* @return	BOOL
* @note
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::Get(const KEY& tKey, T& tData)
{
	const AL_TreeNodeBinSearchSeq<T, KEY>* pGet = GetNode(tKey);
	if (NULL == pGet) {
		//can not get the node
		return FALSE;
	}
	
	//Recursion search
	tData = pGet->GetData();
	return TRUE;
}

/**
* Insert
*
* @param	const T& tData <IN> 
* @param	const KEY& tKey <IN> 
* @return	BOOL
* @note
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::Insert(const T& tData, const KEY& tKey)
{
	//Recursion Insert
	return Insert(m_pRootNode, tData, tKey);
}

/**
* Remove
*
* @param	const KEY& tKey <IN>
* @return	BOOL
* @note 
* @attention  the current tree node must be in the tree, only remove current node and include it's descendant note
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::Remove(const KEY& tKey)
{
	const AL_TreeNodeBinSearchSeq<T, KEY>* pRemove = GetNode(tKey);
	if (NULL == pRemove) {
		//can not get the node
		return FALSE;
	}

	return Remove(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRemove));
}

/**
* RemoveNode
*
* @param	const KEY& tKey <IN>
* @return	BOOL
* @note 
* @attention  the current tree node must be in the tree, only remove current node and not include it's descendant note
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::RemoveNode(const KEY& tKey)
{
	const AL_TreeNodeBinSearchSeq<T, KEY>* pRemoveNode = GetNode(tKey);
	if (NULL == pRemoveNode) {
		//can not get the node
		return FALSE;
	}

	return RemoveNode(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRemoveNode));
}


/**
* GetChildNodeRightAtNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @return	const AL_TreeNodeBinSearchSeq<T, KEY>*
* @note get the current tree node (pCurTreeNode)'s child node at the position (right)
* @attention
*/
template<typename T, typename KEY> const AL_TreeNodeBinSearchSeq<T, KEY>* 
AL_TreeAVLSeq<T, KEY>::GetChildNodeRightAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}
	return pCurTreeNode->GetChildRight();
}

/**
* GetNode
*
* @param	const KEY& tKey <IN> 
* @return	const AL_TreeNodeBinSearchSeq<T, KEY>* 
* @note
* @attention
*/
template<typename T, typename KEY> const AL_TreeNodeBinSearchSeq<T, KEY>* 
AL_TreeAVLSeq<T, KEY>::GetNode(const KEY& tKey)
{
	if (TRUE == IsEmpty()) {
		return NULL;
	}

	if (NULL == m_pRootNode) {
		return NULL;
	}

	return GetNode(m_pRootNode, tKey);
}

/**
* GetNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
* @param	const KEY& tKey <IN> 
* @return	const AL_TreeNodeBinSearchSeq<T, KEY>* 
* @note		for Recursion search
* @attention
*/
template<typename T, typename KEY> const AL_TreeNodeBinSearchSeq<T, KEY>* 
AL_TreeAVLSeq<T, KEY>::GetNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, const KEY& tKey)
{
	if (NULL == pCurTreeNode) {
		return NULL;
	}

	if (tKey < pCurTreeNode->GetKey()) {
		//search the left child
		return GetNode(pCurTreeNode->GetChildLeft(), tKey);
	}
	else if (pCurTreeNode->GetKey() < tKey) {
		//search the right child
		return GetNode(pCurTreeNode->GetChildRight(), tKey);
	}
	else {
		//find it, pCurTreeNode->GetKey() == tKey
		return pCurTreeNode;
	}
	
	//Recursion End
	return NULL;
}

/**
* IsCompleteTreeBin
*
* @param
* @return	BOOL
* @note Is Complete Binary Tree
* @attention If set binary height of h, the h layer in addition, the other layers (1 ~ h-1) has reached the maximum number of 
             nodes, right to left, the h-layer node number of consecutive missing, this is a complete binary tree .
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::IsCompleteTreeBin() const
{
	if (TRUE == IsEmpty()) {
		return FALSE;
	}
	if (NULL == m_pRootNode) {
		return FALSE;
	}
	
	AL_TreeNodeBinSearchSeq<T, KEY>* pTreeNode;
	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listDescendant;
	if (FALSE == GetDescendantAtNode(m_pRootNode, listDescendant)) {
		return FALSE;
	}

	BOOL bMissing = FALSE;
	for (DWORD dwCnt=0x00; dwCnt<listDescendant.Length(); dwCnt++) {
		if (TRUE ==  listDescendant.Get(dwCnt, pTreeNode)) {
			if (NULL != pTreeNode) {
				if (m_dwHeight > pTreeNode->GetLevel()) {
					//the other layers (1 ~ h-1)
					if (NULL == pTreeNode->GetChildLeft() || NULL == pTreeNode->GetChildRight()) {
						//left or right child not exist!
						return FALSE;
					}
				}
				else {
					//the h-layer
					if (TRUE == bMissing) {
						//node number of consecutive missing
						if (NULL == pTreeNode->GetChildLeft() || NULL == pTreeNode->GetChildRight()) {
							//left or right child not exist!
							return FALSE;
						}
					}

					if (NULL == pTreeNode->GetChildLeft()) {
						//left child not exist!
						bMissing = TRUE;
						if (NULL != pTreeNode->GetChildRight()) {
							//right child exist!
							return FALSE;
						}
					}
					else {
						//left child exist!
						if (NULL == pTreeNode->GetChildRight()) {
							//right child not exist!
							bMissing = TRUE;
						}
					}
				}
			}
			else {
				return FALSE;
			}
		}
		else {
			return FALSE;
		}
	}

	return TRUE;
}

/**
* IsFullTreeBin
*
* @param
* @return	BOOL
* @note Is Full Binary Tree
* @attention A binary tree of height h is 2 ^ h-1 element is called a full binary tree.
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::IsFullTreeBin() const
{
	if (TRUE == IsEmpty()) {
		return FALSE;
	}

	DWORD dwTwo = 2;
	DWORD dwFullTreeBinNum = 1;
	for (DWORD dwFull=0x00; dwFull<GetHeight(); dwFull++) {
		dwFullTreeBinNum *= 2;
	}
	dwFullTreeBinNum -= 1;

	return (dwFullTreeBinNum == GetNodesNum())  ? TRUE:FALSE;
}

/**
* IsBalancedTreeBin
*
* @param
* @return	BOOL
* @note Is Balanced Binary Tree
* @attention 1). It is an empty tree or the left and right subtrees of its height difference absolute value is not more than 1,
             2). left and right subtrees are a balanced binary tree.
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::IsBalancedTreeBin() const
{
	if (TRUE == IsEmpty()) {
		//It is an empty tree
		return TRUE;
	}
	
	if (NULL == m_pRootNode) {
		//not empty tree, but boot node NULL
		return FALSE;
	}

	return IsBalancedTreeBinRecursion(m_pRootNode);
}

/**
* GetChildNodeLeftAtNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @return	const AL_TreeNodeBinSearchSeq<T, KEY>*
* @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, typename KEY> const AL_TreeNodeBinSearchSeq<T, KEY>* 
AL_TreeAVLSeq<T, KEY>::GetChildNodeLeftAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}
	return pCurTreeNode->GetChildLeft();
}

/**
* Insert
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pRecursionNode <IN> 
* @param	const T& tData <IN> 
* @param	const KEY& tKey <IN> 
* @return	BOOL
* @note		for Recursion Insert
* @attention if pRecursionNode may be NULL
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::Insert(const AL_TreeNodeBinSearchSeq<T, KEY>* pRecursionNode, const T& tData, const KEY& tKey)
{
	if (TRUE == IsEmpty()) {
		if (NULL != pRecursionNode) {
			//empty, but has the node
			return FALSE;
		}
		//has no root node, insert as root node
		return InsertAtNode(NULL, 0x00, tData, tKey);
	}
	
	static const AL_TreeNodeBinSearchSeq<T, KEY>* pRecursionNodePre = NULL;		//store the previous node of recursion
	if (NULL == pRecursionNode) {
		if (NULL == pRecursionNodePre) {
			//some thing wrong
			return FALSE;
		}
		//inset to the current tree node
		if (NULL == pRecursionNodePre->GetChildLeft() && NULL == pRecursionNodePre->GetChildRight()) {
			//left and right all NULL
			if (tKey < pRecursionNodePre->GetKey()) {
				//insert the left child
				return InsertLeftAtNode(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRecursionNodePre), tData, tKey);
			}
			else if (pRecursionNodePre->GetKey() < tKey) {
				//insert the right child
				return InsertRightAtNode(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRecursionNodePre), tData, tKey);
			}
			else {
				//error, can not have the same key
				return FALSE;
			}
		}
		else if (NULL == pRecursionNodePre->GetChildLeft() && NULL != pRecursionNodePre->GetChildRight()) {
			//left NULL, right not NULL
			if (tKey < pRecursionNodePre->GetKey()) {
				//insert the left child
				return InsertLeftAtNode(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRecursionNodePre), tData, tKey);
			}
			else {
				//error, can not have the same key
				return FALSE;
			}
		}
		else if (NULL != pRecursionNodePre->GetChildLeft() && NULL == pRecursionNodePre->GetChildRight()) {
			//left not NULL, right NULL
			if (pRecursionNodePre->GetKey() < tKey) {
				return InsertRightAtNode(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRecursionNodePre), tData, tKey);
			}
			else {
				return FALSE;
			}
		}
		else {
			//left not NULL, right not NULL
			return FALSE;
		}
	}
	pRecursionNodePre = pRecursionNode;
	if (tKey < pRecursionNode->GetKey()) {
		//recursion the left child (Insert)
		return Insert(pRecursionNode->GetChildLeft(), tData, tKey);
	}
	else if (pRecursionNode->GetKey() < tKey) {
		//recursion the right child (Insert)
		return Insert(pRecursionNode->GetChildRight(), tData, tKey);
	}
	else {
		//error, can not have the same key
		return FALSE;
	}

	//Recursion End
	return FALSE;
}

/**
* InsertLeftAtNode
*
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	const T& tData <IN> 
* @param	const KEY& tKey <IN> 
* @return	BOOL
* @note insert the tData 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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::InsertLeftAtNode(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, const T& tData, const KEY& tKey)
{
	return InsertAtNode(pCurTreeNode, 0x00, tData, tKey);
}

/**
* InsertRightAtNode
*
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	const T& tData <IN> 
* @param	const KEY& tKey <IN> 
* @return	BOOL
* @note insert the tData 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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::InsertRightAtNode(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, const T& tData, const KEY& tKey)
{
	return InsertAtNode(pCurTreeNode, 0x01, tData, tKey);
}

/**
* InsertAtNode
*
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
* @param	DWORD dwIndex <IN>
* @param	const T& tData <IN>
* @param	const KEY& tKey <IN> 
* @return	BOOL
* @note insert the tData 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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::InsertAtNode(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, DWORD dwIndex, const T& tData, const KEY& tKey)
{
	if (TRUE == IsEmpty()) {
		if (NULL != pCurTreeNode) {
			//error can not insert to the current node pCurTreeNode, is not exist in the tree
			return FALSE;
		}
		else {
			m_pTreeNode[m_dwUsed].SetData(tData);
			m_pTreeNode[m_dwUsed].SetKey(tKey);
			m_pTreeNode[m_dwUsed].SetLevel(0x00);

			m_pRootNode = &m_pTreeNode[m_dwUsed];
			m_dwUsed++;
			m_dwDegree = 0x00;
			m_dwHeight = 0x00;			//empty tree 0xffffffff (-1)
			m_dwNumNodes++;
			return TRUE;
		}
	}

	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	if (TRUE == IsFull()) {
		// full, need to get more work buffer 
		//can not support Dynamic Expansion
		return FALSE;
		GetBuffer();
	}

	//inset to the current tree node
	m_pTreeNode[m_dwUsed].SetData(tData);
	m_pTreeNode[m_dwUsed].SetKey(tKey);
	m_pTreeNode[m_dwUsed].SetLevel(pCurTreeNode->GetLevel() + 1);
	if (FALSE ==  pCurTreeNode->Insert(dwIndex, &m_pTreeNode[m_dwUsed])) {
		return FALSE;
	}

	DWORD dwCurNodeDegree = 0x00;
	//loop all node to get the current node degree
	if (m_dwDegree < pCurTreeNode->GetDegree()) {
		m_dwDegree = pCurTreeNode->GetDegree();
	}

	if (m_dwHeight < m_pTreeNode[m_dwUsed].GetLevel()) {
		m_dwHeight = m_pTreeNode[m_dwUsed].GetLevel();
	}
	m_dwUsed++;
	m_dwNumNodes++;
	
	//self balancing
	return SelfBalancing(&m_pTreeNode[m_dwUsed-1]);
}


/**
* SelfBalancing
*
* @param AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
* @return	BOOL
* @note By rotating unbalanced node to make re-balanced binary tree, and find, insert and delete operations time complexity is 
		O (log n) in the average and worst-case
* @attention AVL tree rotation , a total of four cases, note that all cases are rotated around so that the first node in a 
			binary tree imbalance expanded .
			1. LL type
				Left child of a balanced binary tree left child node to insert a new node , so that the node is no longer 
				balanced . At this time need only to rotate the tree to the right , as shown, the original left child A 
				becomes the parent node B , A becomes the right child and the right subtree of the original B to the left 
				sub A tree , note after the rotation Brh is ( forget the a solid line between Brh marked on the map ) A left 
				subtree
			2. RR type
				The right of a child's balanced binary tree right child nodes insert a new node , so that the node is no longer 
				balanced . Then just put the tree once rotated to the left , as shown in Figure A former right child becomes 
				the parent node B , A becomes its left child , and the original left subtree Blh B becomes A right subtree.
			3. LR type
				Left child of the right child nodes of a balanced binary tree, a new node is inserted so that the node is no 
				longer balanced . At this time needs to be rotated twice, only once the rotation is balanced binary tree can 
				not make again . As shown, a Node B , after the rotation , in the binary tree node A can not maintain a balance 
				in accordance with still left RR type , then the need to rotate once again to the right.
			4. RL type
				The right of a child's balanced binary tree left child node to insert a new node , so that the node is no 
				longer balanced . Similarly , when the need to rotate the two , opposite the direction of rotation with the 
				LR model .
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::SelfBalancing(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode)
{
	const AL_TreeNodeBinSearchSeq<T, KEY>* pRotateTreeNode = GetRotateNode(pCurTreeNode);
	if (NULL == pRotateTreeNode) {
		return FALSE;
	}
	if (GetRootNode() ==  pRotateTreeNode) {
		// can not find the rotate node
		return TRUE;
	}

	if (pRotateTreeNode == pRotateTreeNode->GetParent()->GetChildRight()) {
		//unbalanced node's right child (rotate node). (L)
		if (pCurTreeNode->GetKey() > pRotateTreeNode->GetKey()) {
			//right child (rotate node)'s right child tree. (L)
			/*2. LL type
				The right of a child's balanced binary tree right child nodes insert a new node , so that the node is no longer 
				balanced . Then just put the tree once rotated to the left , as shown in Figure A former right child becomes 
				the parent node B , A becomes its left child , and the original left subtree Blh B becomes A right subtree.*/
			//Right Rotate once
			return RotateLeft(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRotateTreeNode));
		}
		else if (pCurTreeNode->GetKey() < pRotateTreeNode->GetKey()) {
			//right child (rotate node)'s left child tree. (R)
			/*4. RL type
				The right of a child's balanced binary tree left child node to insert a new node , so that the node is no 
				longer balanced . Similarly , when the need to rotate the two , opposite the direction of rotation with the 
				LR model .*/
			//Right Rotate once and then, Left Rotate once
			if (FALSE == RotateRight(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRotateTreeNode))) {
				return FALSE;
			}
			pRotateTreeNode = GetRotateNode(pRotateTreeNode->GetParent());
			if (NULL == pRotateTreeNode) {
				return FALSE;
			}
			if (GetRootNode() ==  pRotateTreeNode) {
				// can not find the rotate node (RL type need to rotate twice)
				return FALSE;
			}

			return RotateLeft(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRotateTreeNode));
		}
		else {
			//error, can not have the case
			return FALSE;
		}
	}
	else if (pRotateTreeNode == pRotateTreeNode->GetParent()->GetChildLeft()) {
		//unbalanced node's left child (rotate node). (R)
		if (pCurTreeNode->GetKey() > pRotateTreeNode->GetKey()) {
			//left child (rotate node)'s right child tree. (L)
			/*3. LR type
				Left child of the right child nodes of a balanced binary tree, a new node is inserted so that the node is no 
				longer balanced . At this time needs to be rotated twice, only once the rotation is balanced binary tree can 
				not make again . As shown, a Node B , after the rotation , in the binary tree node A can not maintain a balance 
				in accordance with still left RR type , then the need to rotate once again to the right.*/
			//Left Rotate once and then, Right Rotate once
			if (FALSE == RotateLeft(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRotateTreeNode))) {
				return FALSE;
			}
			pRotateTreeNode = GetRotateNode(pRotateTreeNode->GetParent());
			if (NULL == pRotateTreeNode) {
				return FALSE;
			}
			if (GetRootNode() ==  pRotateTreeNode) {
				// can not find the rotate node (LR type need to rotate twice)
				return FALSE;
			}

			return RotateRight(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRotateTreeNode));
		}
		else if (pCurTreeNode->GetKey() < pRotateTreeNode->GetKey()) {
			//left child (rotate node)'s left child tree. (R)
			/*1. RR type
				Left child of a balanced binary tree left child node to insert a new node , so that the node is no longer 
				balanced . At this time need only to rotate the tree to the right , as shown, the original left child A 
				becomes the parent node B , A becomes the right child and the right subtree of the original B to the left 
				sub A tree , note after the rotation Brh is ( forget the a solid line between Brh marked on the map ) A left 
				subtree*/
			//Right Rotate once
			return RotateRight(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pRotateTreeNode));
		}
		else {
			//error, can not have the case
			return FALSE;
		}
	}
	else {
		//error, can not have the case
		return FALSE;
	}
	
	return FALSE;
}

/**
* SelfBalancing
*
* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
* @return	BOOL
* @note By rotating unbalanced node to make re-balanced binary tree, and find, insert and delete operations time complexity is 
		O (log n) in the average and worst-case
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::RotateLeft(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode)
{
	//get parent and right child node
	AL_TreeNodeBinSearchSeq<T, KEY>* pUnbalancedTreeNode = pCurTreeNode->GetParent();
	AL_TreeNodeBinSearchSeq<T, KEY>* pChildRightTreeNode = pCurTreeNode->GetChildRight();
	if (NULL == pUnbalancedTreeNode || NULL == pChildRightTreeNode) {
		return FALSE;
	}

	if (pCurTreeNode == pUnbalancedTreeNode->GetChildRight()) {
		//○ unbalanced node
		//● rotate node
		//◎ insert node in the child tree of  rotate node
		/************************************************************************/
		/*		○							●
					●			→		○		◎
						◎														*/
		/************************************************************************/
		pUnbalancedTreeNode->Remove(pCurTreeNode);
		AL_TreeNodeBinSearchSeq<T, KEY>* pUnbalancedParen = pUnbalancedTreeNode->GetParent();
		if (NULL == pUnbalancedParen) {
			//unbalanced node is the root node
			//update the node's level
			pCurTreeNode->SetLevel(0);
			if (NULL != pCurTreeNode->GetChildLeft()) {
				AL_TreeNodeBinSearchSeq<T, KEY>* pChildLeftTemp = pCurTreeNode->GetChildLeft();
				pCurTreeNode->Remove(pChildLeftTemp);
				pCurTreeNode->InsertLeft(pChildLeftTemp);
			}
			if (NULL != pCurTreeNode->GetChildRight()) {
				AL_TreeNodeBinSearchSeq<T, KEY>* pChildRightTemp = pCurTreeNode->GetChildRight();
				pCurTreeNode->Remove(pChildRightTemp);
				pCurTreeNode->InsertRight(pChildRightTemp);
			}
			//set root node
			m_pRootNode = pCurTreeNode;
		}
		else {
			//unbalanced node is not the root node
			if (pUnbalancedTreeNode == pUnbalancedParen->GetChildLeft()) {
				pUnbalancedParen->Remove(pUnbalancedTreeNode);
				pUnbalancedParen->InsertLeft(pCurTreeNode);
			}
			else if (pUnbalancedTreeNode == pUnbalancedParen->GetChildRight()) {
				pUnbalancedParen->Remove(pUnbalancedTreeNode);
				pUnbalancedParen->InsertRight(pCurTreeNode);
			}
			else {
				//not the case
				return FALSE;
			}	
		}

		if (NULL != pCurTreeNode->GetChildLeft()) {
			AL_TreeNodeBinSearchSeq<T, KEY>* pRotateChildLeft = pCurTreeNode->GetChildLeft();
			pCurTreeNode->Remove(pRotateChildLeft);
			pUnbalancedTreeNode->InsertRight(pRotateChildLeft);
		}
		pCurTreeNode->InsertLeft(pUnbalancedTreeNode);
	}
	else if (pCurTreeNode == pUnbalancedTreeNode->GetChildLeft()) {
		//○ unbalanced node
		//● rotate node
		//◎ insert node in the child tree of  rotate node
		/************************************************************************/
		/*			○							○
				●				→			◎
					◎					●								`		*/
		/************************************************************************/
		pUnbalancedTreeNode->Remove(pCurTreeNode);
		pCurTreeNode->Remove(pChildRightTreeNode);
		if (NULL != pChildRightTreeNode->GetChildLeft()) {
			AL_TreeNodeBinSearchSeq<T, KEY>* pChildRightChildLeft = pChildRightTreeNode->GetChildLeft();
			pChildRightTreeNode->Remove(pChildRightChildLeft);
			pCurTreeNode->InsertRight(pChildRightChildLeft);
		}
		pChildRightTreeNode->InsertLeft(pCurTreeNode);
		pUnbalancedTreeNode->InsertLeft(pChildRightTreeNode);
	}
	else {
		//not the case
		return FALSE;
	}
	
	return TRUE;
}

/**
* RotateRight
*
* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
* @return	BOOL
* @note By rotating unbalanced node to make re-balanced binary tree, and find, insert and delete operations time complexity is 
		O (log n) in the average and worst-case
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::RotateRight(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode)
{
	//get parent and left child node
	AL_TreeNodeBinSearchSeq<T, KEY>* pUnbalancedTreeNode = pCurTreeNode->GetParent();
	AL_TreeNodeBinSearchSeq<T, KEY>* pChildLeftTreeNode = pCurTreeNode->GetChildLeft();
	if (NULL == pUnbalancedTreeNode || NULL == pChildLeftTreeNode) {
		return FALSE;
	}

	if (pCurTreeNode == pUnbalancedTreeNode->GetChildLeft()) {
		//○ unbalanced node
		//● rotate node
		//◎ insert node in the child tree of  rotate node
		/************************************************************************/
		/*				○					●
					●			→		◎		○
				◎																*/
		/************************************************************************/
		pUnbalancedTreeNode->Remove(pCurTreeNode);

		AL_TreeNodeBinSearchSeq<T, KEY>* pUnbalancedParen = pUnbalancedTreeNode->GetParent();
		if (NULL == pUnbalancedParen) {
			//unbalanced node is the root node
			//update the node's level
			pCurTreeNode->SetLevel(0);
			if (NULL != pCurTreeNode->GetChildLeft()) {
				AL_TreeNodeBinSearchSeq<T, KEY>* pChildLeftTemp = pCurTreeNode->GetChildLeft();
				pCurTreeNode->Remove(pChildLeftTemp);
				pCurTreeNode->InsertLeft(pChildLeftTemp);
			}
			if (NULL != pCurTreeNode->GetChildRight()) {
				AL_TreeNodeBinSearchSeq<T, KEY>* pChildRightTemp = pCurTreeNode->GetChildRight();
				pCurTreeNode->Remove(pChildRightTemp);
				pCurTreeNode->InsertRight(pChildRightTemp);
			}
			//set root node
			m_pRootNode = pCurTreeNode;
		}
		else {
			//unbalanced node is not the root node
			if (pUnbalancedTreeNode == pUnbalancedParen->GetChildLeft()) {
				pUnbalancedParen->Remove(pUnbalancedTreeNode);
				pUnbalancedParen->InsertLeft(pCurTreeNode);
			}
			else if (pUnbalancedTreeNode == pUnbalancedParen->GetChildRight()) {
				pUnbalancedParen->Remove(pUnbalancedTreeNode);
				pUnbalancedParen->InsertRight(pCurTreeNode);
			}
			else {
				//not the case
				return FALSE;
			}
		}
		if (NULL != pCurTreeNode->GetChildRight()) {
			AL_TreeNodeBinSearchSeq<T, KEY>* pRotateChildRight = pCurTreeNode->GetChildRight();
			pCurTreeNode->Remove(pRotateChildRight);
			pUnbalancedTreeNode->InsertLeft(pRotateChildRight);
		}
		pCurTreeNode->InsertRight(pUnbalancedTreeNode);
	}
	else if (pCurTreeNode == pUnbalancedTreeNode->GetChildRight()) {
		//○ unbalanced node
		//● rotate node
		//◎ insert node in the child tree of  rotate node
		/************************************************************************/
		/*		○					○
					●		→			◎
				◎							●								`*/
		/************************************************************************/
		pUnbalancedTreeNode->Remove(pCurTreeNode);
		pCurTreeNode->Remove(pChildLeftTreeNode);
		if (NULL != pChildLeftTreeNode->GetChildRight()) {
			AL_TreeNodeBinSearchSeq<T, KEY>* pChildLeftChildRight = pChildLeftTreeNode->GetChildRight();
			pChildLeftTreeNode->Remove(pChildLeftChildRight);
			pCurTreeNode->InsertLeft(pChildLeftChildRight);
		}
		pChildLeftTreeNode->InsertRight(pCurTreeNode);
		pUnbalancedTreeNode->InsertRight(pChildLeftTreeNode);
	}
	else {
		//not the case
		return FALSE;
	}
	  
	return TRUE;
}

/**
* GetRotateNode
*
* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
* @return const AL_TreeNodeBinSearchSeq<T, KEY>*
			1. NULL: a abnormal case, NULL will be returned
			2. RootNode: can not find rotate node, RootNode will be returned
			3. Other Node: find rotate node, Other Node will be returned
* @note To back from inserted up to the root node to find a minimal loss of balance tree root pointer
* @attention Unbalanced node is the parent node of RotateNode
*/
template<typename T, typename KEY> const AL_TreeNodeBinSearchSeq<T, KEY>* 
AL_TreeAVLSeq<T, KEY>::GetRotateNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return NULL;
	}
	
	const AL_TreeNodeBinSearchSeq<T, KEY>* pRotateTreeNode = pCurTreeNode;
	while (NULL != pCurTreeNode) {
		pCurTreeNode = pCurTreeNode->GetParent();
		if (FALSE == IsBalancedNode(pCurTreeNode)){
			break;
		}
		pRotateTreeNode = pCurTreeNode;
	}

	return pRotateTreeNode;
}
	
/**
* RemoveNode
*
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @return	BOOL
* @note 
* @attention  the current tree node must be in the tree, only remove current node and not include it's descendant note
			1). p a leaf node, just delete the node, and then modify its parent node pointer (note points is the root node and not 
			the root);
			2). p for the single node (ie, only the left subtree or right subtree). Let p and p subtree connected to the node's father, 
			then delete p; (note points is the root node and not the root);
			3). p left subtree and right subtree are not empty. Find p's successor y, because y certainly no left subtree, so you can 
			delete y, and let y father node becomes y's right subtree father node, and use the value of y instead of p values​​; or 
			method two is to find p precursor x, x certainly no right subtree, so you can delete x, and let x, y father node becomes 
			the father of the left subtree of the node;
*/
template<typename T, typename KEY> BOOL
AL_TreeAVLSeq<T, KEY>::RemoveNode(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode)
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}
	
	AL_TreeNodeBinSearchSeq<T, KEY>* pCurNodeParent = NULL;
	if (TRUE == pCurTreeNode->IsLeaf()) {
//	if (0x00 == pCurTreeNode->GetDegree()) {
		//leaf node; see 1)
		pCurNodeParent = pCurTreeNode->GetParent();
		if (NULL != pCurNodeParent) {
			if (FALSE == pCurNodeParent->Remove(pCurTreeNode)) {
				return FALSE;
			}
		}
		else {
			//root node
			if (m_pRootNode == pCurTreeNode) {
				//judge root node
				m_pRootNode = NULL;
			}
			else {
				return FALSE;
			}
		}
	}
	else if (0x01 == pCurTreeNode->GetDegree()) {
		//not leaf node, single node; see 2)
		//get the child node
		AL_TreeNodeBinSearchSeq<T, KEY>* pChildeNode = NULL;
		if (NULL != pCurTreeNode->GetChildLeft()) {
			//left child exist
			pChildeNode = pCurTreeNode->GetChildLeft();
		}
		if (NULL != pCurTreeNode->GetChildRight()) {
			//right child exist
			pChildeNode = pCurTreeNode->GetChildRight();
		}
		
		if (NULL ==  pChildeNode) {
			//can not get child node
			return FALSE;
		}
		pChildeNode->RemoveParent();

		pCurNodeParent = pCurTreeNode->GetParent();
		if (NULL != pCurNodeParent) {
			if (pCurTreeNode == pCurNodeParent->GetChildLeft()) {
				//current node as child left exist
				pCurNodeParent->Remove(pCurTreeNode);
				if (FALSE == pCurNodeParent->InsertLeft(pChildeNode)) {
					return FALSE;
				}
			}
			else {
				//current node as child right exist
				pCurNodeParent->Remove(pCurTreeNode);
				if (FALSE == pCurNodeParent->InsertRight(pChildeNode)) {
					return FALSE;
				}
			}
		}
		else {
			//root node
			if (m_pRootNode == pCurTreeNode) {
				//judge root node
				m_pRootNode = pChildeNode;
			}
			else {
				return FALSE;
			}
		}
	}
	else if (0x02 == pCurTreeNode->GetDegree()){
		// left and right are not empty; see 3)
		AL_TreeNodeBinSearchSeq<T, KEY>* pChildLeft = pCurTreeNode->GetChildLeft();
		AL_TreeNodeBinSearchSeq<T, KEY>* pChildRight = pCurTreeNode->GetChildRight();
		if (NULL ==  pChildLeft|| NULL == pChildRight) {
			//the left or right child not exist
			return FALSE;
		}
		AL_TreeNodeBinSearchSeq<T, KEY>* pReplace = NULL;
		if (FALSE == GetSuccessor(pChildLeft, pReplace)) {
			//get the successor failed
			return FALSE;
		}
		if (NULL == pReplace) {
			//get the successor failed
			return FALSE;
		}

		//pReplace must have not the right child
		if (NULL != pReplace->GetChildRight()) {
			//judge it
			return FALSE;
		}

		AL_TreeNodeBinSearchSeq<T, KEY>* pReplaceParent = pReplace->GetParent();
		if (NULL == pReplaceParent) {
			return FALSE;
		}
		AL_TreeNodeBinSearchSeq<T, KEY>* pReplaceChildLeft = pReplace->GetChildLeft();
		if (FALSE == pReplaceParent->Remove(pReplace) 
			|| FALSE == pReplace->RemoveParent() 
			|| FALSE == pReplace->Remove(pReplaceChildLeft)) {
			return FALSE;
		}
	
		if (NULL != pReplaceChildLeft) {
			//left child exist
			pReplaceChildLeft->RemoveParent();
			if (FALSE == pReplaceParent->InsertRight(pReplaceChildLeft)) {
				return FALSE;
			}
		}

		//insert current node's child to the replace node
		pChildLeft->RemoveParent();
		pChildRight->RemoveParent();
		if (pReplace != pChildLeft) {
			if (FALSE == pReplace->InsertLeft(pChildLeft)) {
					return FALSE;
			}
		}
		if (pReplace != pChildRight) {
			if (FALSE == pReplace->InsertRight(pChildRight)) {
				return FALSE;
			}
		}
		
		pCurNodeParent = pCurTreeNode->GetParent();
		if (NULL != pCurNodeParent) {
			//current node has parent
			if (pCurTreeNode == pCurNodeParent->GetChildLeft()) {
				//current node as child left exist
				pCurNodeParent->Remove(pCurTreeNode);
				if (FALSE == pCurNodeParent->InsertLeft(pReplace)) {
					return FALSE;
				}
			}
			else {
				//current node as child right exist
				pCurNodeParent->Remove(pCurTreeNode);
				if (FALSE == pCurNodeParent->InsertRight(pReplace)) {
					return FALSE;
				}
			}
		}
		else {
			if (m_pRootNode == pCurTreeNode) {
				//root node
				m_pRootNode = pReplace;
			}
			else {
				return FALSE;
			}
		}
	}
	else {
		//Binary Search Tree only two child node, can not be this case
		return FALSE;
	}	

	//delete the current node
	pCurTreeNode->Clear();
	m_dwNumNodes--;
	return TRUE;
}

/**
* Remove
*
* @param	AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @return	BOOL
* @note 
* @attention  the current tree node must be in the tree, remove current node and include it's descendant note
*/
template<typename T, typename KEY> BOOL
AL_TreeAVLSeq<T, KEY>::Remove(AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode)
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listTreeNodeDescendant;
	AL_TreeNodeBinSearchSeq<T, KEY>* pTreeNodeDescendant = NULL;
	if (TRUE == pCurTreeNode->GetDescendant(listTreeNodeDescendant)) {
		//delete the descendant node
		for (DWORD dwRemoveCnt=0x00; dwRemoveCnt<listTreeNodeDescendant.Length(); dwRemoveCnt++) {
			if (TRUE == listTreeNodeDescendant.Get(dwRemoveCnt, pTreeNodeDescendant)) {
				if (NULL != pTreeNodeDescendant) {
					pTreeNodeDescendant->Clear();
				}
				else {
					return FALSE;
				}
			}
			else {
				return FALSE;
			}
		}
	}

	AL_TreeNodeBinSearchSeq<T, KEY>* pNodeParent = pCurTreeNode->GetParent();
	if (NULL == pNodeParent && m_pRootNode != pCurTreeNode) {
		//not root node and has no parent node
		return FALSE;
	}
	if (NULL != pNodeParent) {
		//parent exist, remove the child node (pCurTreeNode)
		pNodeParent->Remove(pCurTreeNode);
	}
	
	if (m_pRootNode == pCurTreeNode) {
		//remove the root node
		m_pRootNode = NULL;
	}

	pCurTreeNode->Clear();
	m_dwNumNodes -= (listTreeNodeDescendant.Length() + 1);

	if (FALSE == RecalcDegreeHeight()) {
		return FALSE;
	}
	return TRUE;
}

/**
* PreOrderTraversal
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
* @return	BOOL
* @note Pre-order traversal
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::PreOrderTraversal(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	listOrder.Clear();

	//Recursion Traversal
	return PreOrderTraversalRecursion(pCurTreeNode, listOrder);

	//Not Recursion Traversal
	AL_StackSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> cStack;
	AL_TreeNodeBinSearchSeq<T, KEY>* pTreeNode = const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode);

	while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {
		while (NULL != pTreeNode) {
			listOrder.InsertEnd(pTreeNode);
			if (NULL != pTreeNode->GetChildRight()) {
				//push the child right to stack
				cStack.Push(pTreeNode->GetChildRight());
			}
			pTreeNode = pTreeNode->GetChildLeft();
		}

		if (TRUE == cStack.Pop(pTreeNode)) {
			if (NULL == pTreeNode) {
				return FALSE;
			}
		}
		else {
			return FALSE;
		}

	}
	return TRUE;
}

/**
* InOrderTraversal
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
* @return	BOOL
* @note In-order traversal
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::InOrderTraversal(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	listOrder.Clear();

	//Recursion Traversal
	return InOrderTraversalRecursion(pCurTreeNode, listOrder);

	//Not Recursion Traversal
	AL_StackSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> cStack;
	AL_TreeNodeBinSearchSeq<T, KEY>* pTreeNode = const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode);

	while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {
		while (NULL != pTreeNode) {
			cStack.Push(pTreeNode);
			pTreeNode = pTreeNode->GetChildLeft();
		}

		if (TRUE == cStack.Pop(pTreeNode)) {
			if (NULL !=  pTreeNode) {
				listOrder.InsertEnd(pTreeNode);
				if (NULL != pTreeNode->GetChildRight()){
					//child right exist, push the node, and loop it's left child to push
					pTreeNode = pTreeNode->GetChildRight();
				}
				else {
					//to pop the node in the stack
					pTreeNode = NULL;
				}
			}
			else {
				return FALSE;
			}
		}
		else {
			return FALSE;
		}
	}

	return TRUE;
}

/**
* PostOrderTraversal
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
* @return	BOOL
* @note Post-order traversal
* @attention
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::PostOrderTraversal(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	listOrder.Clear();

	//Recursion Traversal
	return PostOrderTraversalRecursion(pCurTreeNode, listOrder);

	//Not Recursion Traversal
	AL_StackSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> cStack;
	AL_TreeNodeBinSearchSeq<T, KEY>* pTreeNode = const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode);
	AL_StackSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> cStackReturn;
	AL_TreeNodeBinSearchSeq<T, KEY>* pTreeNodeReturn = NULL;

	while (TRUE != cStack.IsEmpty() || NULL != pTreeNode) {
		while (NULL != pTreeNode) {
			cStack.Push(pTreeNode);
			if (NULL != pTreeNode->GetChildLeft()) {
				pTreeNode = pTreeNode->GetChildLeft();
			}
			else {
				//has not left child, get the right child
				pTreeNode = pTreeNode->GetChildRight();
			}
		}

		if (TRUE == cStack.Pop(pTreeNode)) {
			if (NULL !=  pTreeNode) {
				listOrder.InsertEnd(pTreeNode);
				if (NULL != pTreeNode->GetChildLeft() && NULL != pTreeNode->GetChildRight()){
					//child right exist
					cStackReturn.Top(pTreeNodeReturn);
					if (pTreeNodeReturn != pTreeNode) {
						listOrder.RemoveAt(listOrder.Length()-1);
						cStack.Push(pTreeNode);
						cStackReturn.Push(pTreeNode);
						pTreeNode = pTreeNode->GetChildRight();
					}
					else {
						//to pop the node in the stack
						cStackReturn.Pop(pTreeNodeReturn);
						pTreeNode = NULL;
					}
				}
				else {
					//to pop the node in the stack
					pTreeNode = NULL;
				}
			}
			else {
				return FALSE;
			}
		}
		else {
			return FALSE;
		}
	}

	return TRUE;
}

/**
* LevelOrderTraversal
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
* @return	BOOL
* @note Level-order traversal
* @attention 
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::LevelOrderTraversal(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}
	listOrder.Clear();
	/*
	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listNodeOrder;
	listNodeOrder.InsertEnd(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode));
	//loop the all node
	DWORD dwNodeOrderLoop = 0x00;
	AL_TreeNodeBinSearchSeq<T, KEY>* pNodeOrderLoop = NULL;
	AL_TreeNodeBinSearchSeq<T, KEY>* pNodeOrderChild = NULL;
	while (TRUE == listNodeOrder.Get(pNodeOrderLoop, dwNodeOrderLoop)) {
		dwNodeOrderLoop++;
		if (NULL != pNodeOrderLoop) {
			listOrder.InsertEnd(pNodeOrderLoop);
			pNodeOrderChild = pNodeOrderLoop->GetChildLeft();
			if (NULL != pNodeOrderChild) {
				queueOrder.Push(pNodeOrderChild);
			}
			pNodeOrderChild = pNodeOrderLoop->GetChildRight();
			if (NULL != pNodeOrderChild) {
				queueOrder.Push(pNodeOrderChild);
			}
		}
		else {
			//error
			return FALSE;
		}
	}
	return TRUE;
	*/
	
	AL_QueueSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> queueOrder;
	queueOrder.Push(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode));
	
	AL_TreeNodeBinSearchSeq<T, KEY>* pNodeOrderLoop = NULL;
	AL_TreeNodeBinSearchSeq<T, KEY>* pNodeOrderChild = NULL;
	while (FALSE == queueOrder.IsEmpty()) {
		if (TRUE == queueOrder.Pop(pNodeOrderLoop)) {
			if (NULL != pNodeOrderLoop) {
				listOrder.InsertEnd(pNodeOrderLoop); 
				pNodeOrderChild = pNodeOrderLoop->GetChildLeft();
				if (NULL != pNodeOrderChild) {
					queueOrder.Push(pNodeOrderChild);
				}
				pNodeOrderChild = pNodeOrderLoop->GetChildRight();
				if (NULL != pNodeOrderChild) {
					queueOrder.Push(pNodeOrderChild);
				}
			}
			else {
				return FALSE;
			}
		}
		else {
			return FALSE;
		}
	}
	return TRUE;
}

/**
* PreOrderTraversal
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
* @return	BOOL
* @note Pre-order traversal
* @attention Recursion Traversal
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::PreOrderTraversalRecursion(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	//Do Something with node
	if (FALSE == listOrder.InsertEnd(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode))) {
		return FALSE;
	}

	if(NULL != pCurTreeNode->GetChildLeft()) {
		if (FALSE == PreOrderTraversalRecursion(pCurTreeNode->GetChildLeft(), listOrder)) {
			return FALSE;
		}	
	}

	if(NULL != pCurTreeNode->GetChildRight()) {
		if (FALSE == PreOrderTraversalRecursion(pCurTreeNode->GetChildRight(), listOrder)) {
			return FALSE;
		}
	}

	//Recursion End
	return TRUE;
}

/**
* InOrderTraversal
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
* @return	BOOL
* @note In-order traversal
* @attention Recursion Traversal
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::InOrderTraversalRecursion(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	if(NULL != pCurTreeNode->GetChildLeft()) {
		if (FALSE == InOrderTraversalRecursion(pCurTreeNode->GetChildLeft(), listOrder)) {
			return FALSE;
		}
	}

	//Do Something with node
	if (FALSE == listOrder.InsertEnd(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode))) {
		return FALSE;
	}

	if(NULL != pCurTreeNode->GetChildRight()) {
		if (FALSE == InOrderTraversalRecursion(pCurTreeNode->GetChildRight(), listOrder)) {
			return FALSE;
		}
	}

	//Recursion End
	return TRUE;
}

/**
* PostOrderTraversal
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder <OUT>
* @return	BOOL
* @note Post-order traversal
* @attention Recursion Traversal
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::PostOrderTraversalRecursion(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listOrder) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	if(NULL != pCurTreeNode->GetChildLeft()) {
		if (FALSE == PostOrderTraversalRecursion(pCurTreeNode->GetChildLeft(), listOrder)) {
			return FALSE;
		}
	}

	if(NULL != pCurTreeNode->GetChildRight()) {
		if (FALSE == PostOrderTraversalRecursion(pCurTreeNode->GetChildRight(), listOrder)) {
			return FALSE;
		}
	}

	//Do Something with node
	if (FALSE == listOrder.InsertEnd(const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode))) {
		return FALSE;
	}

	//Recursion End
	return TRUE;
}

/**
* IsBalancedTreeBinRecursion
*
* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @return	BOOL
* @note Is Balanced Binary Tree
* @attention 1). It is an empty tree or the left and right subtrees of its height difference absolute value is not more than 1,
             2). left and right subtrees are a balanced binary tree.
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::IsBalancedTreeBinRecursion(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	if (FALSE == IsBalancedNode(pCurTreeNode)) {
		return FALSE;
	}

	if (NULL != pCurTreeNode->GetChildLeft()){
		if (FALSE == IsBalancedTreeBinRecursion(pCurTreeNode->GetChildLeft())) {
			return FALSE;
		}
	}

	if (NULL != pCurTreeNode->GetChildRight()){
		if (FALSE == IsBalancedTreeBinRecursion(pCurTreeNode->GetChildRight())) {
			return FALSE;
		}
	}

	//Recursion End
	return TRUE;
}

/**
* IsBalancedNode
*
* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @return	BOOL
* @note Is Balanced Node
* @attention the left and right subtrees of its height difference absolute value is not more than 1
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::IsBalancedNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	if (NULL == pCurTreeNode->GetChildLeft()
		&& NULL == pCurTreeNode->GetChildRight()) {
		//Balanced Node
	}
	else if (NULL != pCurTreeNode->GetChildLeft()
		&& NULL == pCurTreeNode->GetChildRight()) {
			if (0x00 != CalcHeight(pCurTreeNode->GetChildLeft())) {
				return FALSE;
			}
	}
	else if (NULL == pCurTreeNode->GetChildLeft()
		&& NULL != pCurTreeNode->GetChildRight()) {
			if (0x00 != CalcHeight(pCurTreeNode->GetChildRight())) {
				return FALSE;
			}
	}
	else {
		if (0x01 < AL_Math::AbsMinus(CalcHeight(pCurTreeNode->GetChildLeft()), CalcHeight(pCurTreeNode->GetChildRight()))){
			//the left and right subtrees of its height difference absolute value is more than 1
			return FALSE;
		}
	}

	return TRUE;
}

/**
* GetSiblingAtNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listSibling <OUT>
* @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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::GetSiblingAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listSibling) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}
	
	listSibling.Clear();
	return pCurTreeNode->GetSibling(listSibling);
}

/**
* GetAncestorAtNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listAncestor <OUT>
* @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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::GetAncestorAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listAncestor) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	listAncestor.Clear();
	return pCurTreeNode->GetAncestor(listAncestor);
}

/**
* GetDescendantAtNode
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @param	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listDescendant <OUT>
* @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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::GetDescendantAtNode(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listDescendant) const
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	listDescendant.Clear();
	return pCurTreeNode->GetDescendant(listDescendant);
}

/**
* RecalcDegreeHeight
*
* @param	
* @return	BOOL
* @note recalculate Degree Height
* @attention 
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::RecalcDegreeHeight()
{
	if (NULL == m_pRootNode) {
		if (TRUE == IsEmpty()) {
			m_dwDegree = 0x00;
			m_dwHeight = TREEAVLSEQ_HEIGHTINVALID;
			return TRUE;
		}
		else {
			return FALSE;
		}
	}
	m_dwDegree = CalcDegree(m_pRootNode);
	m_dwHeight = CalcHeight(m_pRootNode);

	if ( (0x00==m_dwDegree && TRUE==m_pRootNode->IsLeaf())
		|| TREEAVLSEQ_HEIGHTINVALID == m_dwHeight) {
			return FALSE;
	}
	return TRUE;
}

/**
* CalcDegree
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @return	DWORD
* @note calculate degree form current tree node
* @attention 
*/
template<typename T, typename KEY> DWORD 
AL_TreeAVLSeq<T, KEY>::CalcDegree(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return 0x00;
	}
	DWORD dwDegree = pCurTreeNode->GetDegree();

	//loop all the node
	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listTreeNodeDescendant;
	if (TRUE == m_pRootNode->GetDescendant(listTreeNodeDescendant)) {
		DWORD dwNumNodes = listTreeNodeDescendant.Length() + 1;
		if (m_dwNumNodes != dwNumNodes) {
			return 0x00;
		}

		AL_TreeNodeBinSearchSeq<T, KEY>* pTreeNodeDescendant = NULL;
		for (DWORD dwLoopCnt=0x00; dwLoopCnt<listTreeNodeDescendant.Length(); dwLoopCnt++) {
			if (TRUE == listTreeNodeDescendant.Get(dwLoopCnt, pTreeNodeDescendant)) {
				if (NULL != pTreeNodeDescendant) {
					if (dwDegree < pTreeNodeDescendant->GetDegree()) {
						dwDegree = pTreeNodeDescendant->GetDegree();
					}
				}
				else {
					//error
					return 0x00;
				}
			}
			else {
				//error
				return 0x00;
			}
		}
	}
	else {
		return 0x00;
	}

	return dwDegree;
}

/**
* CalcHeight
*
* @param	const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN> 
* @return	DWORD
* @note calculate height form current tree node
* @attention 
*/
template<typename T, typename KEY> DWORD 
AL_TreeAVLSeq<T, KEY>::CalcHeight(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode) const
{
	if (NULL == pCurTreeNode) {
		return TREEAVLSEQ_HEIGHTINVALID;
	}
	DWORD dwHeight = pCurTreeNode->GetLevel();

	//loop all the node
	AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*> listTreeNodeDescendant;
	if (TRUE == pCurTreeNode->GetDescendant(listTreeNodeDescendant)) {
		DWORD dwNumNodes = listTreeNodeDescendant.Length() + 1;
// 		if (m_dwNumNodes != dwNumNodes) {
// 			return TREEAVLSEQ_HEIGHTINVALID;
// 		}

		AL_TreeNodeBinSearchSeq<T, KEY>* pTreeNodeDescendant = NULL;
		for (DWORD dwLoopCnt=0x00; dwLoopCnt<listTreeNodeDescendant.Length(); dwLoopCnt++) {
			if (TRUE == listTreeNodeDescendant.Get(dwLoopCnt, pTreeNodeDescendant)) {
				if (NULL != pTreeNodeDescendant) {
					if (dwHeight < pTreeNodeDescendant->GetLevel()) {
						dwHeight = pTreeNodeDescendant->GetLevel();
					}
				}
				else {
					//error
					return TREEAVLSEQ_HEIGHTINVALID;
				}
			}
			else {
				//error
				return TREEAVLSEQ_HEIGHTINVALID;
			}
		}
	}
	else {
		return TREEAVLSEQ_HEIGHTINVALID;
	}

	return (dwHeight - pCurTreeNode->GetLevel());
}

/**
* GetListDataFormListNode
*
* @param	
* @param	const AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listNode <IN>
* @param	AL_ListSeq<T>& listData <OUT>
* @param	AL_ListSeq<KEY>& listKey <OUT> (default value: AL_ListSeq<KEY>())
* @note
* @attention 
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::GetListDataFormListNode(const AL_ListSeq<AL_TreeNodeBinSearchSeq<T, KEY>*>& listNode, AL_ListSeq<T>& listData, AL_ListSeq<KEY>& listKey) const
{
	AL_TreeNodeBinSearchSeq<T, KEY>* pNodeLoop = NULL;
	listData.Clear();
	listKey.Clear();
	//loop all node in list
	for (DWORD dwLoopCnt=0x00; dwLoopCnt<listNode.Length(); dwLoopCnt++) {
		if (TRUE == listNode.Get(dwLoopCnt, pNodeLoop)) {
			if (NULL != pNodeLoop) {
				if (FALSE == listData.InsertEnd(pNodeLoop->GetData()) 
					|| FALSE == listKey.InsertEnd(pNodeLoop->GetKey())) {
					return FALSE;
				}
			}
			else {
				return FALSE;
			}
		}
		else {
			return FALSE;
		}
	}
	return TRUE;
}

/**
* GetPrecursor
*
* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
* @param AL_TreeNodeBinSearchSeq<T, KEY>*& pQuotePrecursor <OUT>
* @return BOOL
* @note Get Precursor of the current tree node
* @attention Recursion Search
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::GetPrecursor(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_TreeNodeBinSearchSeq<T, KEY>*& pQuotePrecursor)
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	if (NULL != pCurTreeNode->GetChildLeft()) {
		if (FALSE == GetSuccessor(pCurTreeNode->GetChildLeft(), pQuotePrecursor)) {
			return FALSE;
		}
	}
	else {
		pQuotePrecursor = const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode);
	}
	return TRUE;
}

/**
* GetSuccessor
*
* @param const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode <IN>
* @param AL_TreeNodeBinSearchSeq<T, KEY>*& pQuoteSuccessor <OUT>
* @return BOOL
* @note Get Successor of the current tree node
* @attention Recursion Search
*/
template<typename T, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::GetSuccessor(const AL_TreeNodeBinSearchSeq<T, KEY>* pCurTreeNode, AL_TreeNodeBinSearchSeq<T, KEY>*& pQuoteSuccessor)
{
	if (NULL == pCurTreeNode) {
		return FALSE;
	}

	if (NULL != pCurTreeNode->GetChildRight()) {
		if (FALSE == GetSuccessor(pCurTreeNode->GetChildRight(), pQuoteSuccessor)) {
			return FALSE;
		}
	}
	else {
		pQuoteSuccessor = const_cast<AL_TreeNodeBinSearchSeq<T, KEY>*>(pCurTreeNode);
	}
	return TRUE;
}

/**
* 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, typename KEY> VOID 
AL_TreeAVLSeq<T, KEY>::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_TreeNodeBinSearchSeq<T, KEY>[m_dwMaxSize];
		}
		return;
	}

	//we need to get more buffer, store the previous pointer
	AL_TreeNodeBinSearchSeq<T, KEY>* pLastTpye = NULL;

	// it will become to double
	pLastTpye = m_pTreeNode;
	if (TREEAVLSEQ_MAXSIZE == m_dwMaxSize) {
		//can not get more buffer, please check the application
		return;
	}
	else if (TREEAVLSEQ_MAXSIZE/2 < m_dwMaxSize) {
		m_dwMaxSize = TREEAVLSEQ_MAXSIZE;
	}
	else {
		m_dwMaxSize *= 2;
	}
	if(0 < m_dwMaxSize){
		//get the new work buffer
		m_pTreeNode = new AL_TreeNodeBinSearchSeq<T, KEY>[m_dwMaxSize];
	}
	//need to copy the last to the current
	for (DWORD dwCpy=0x00; 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, typename KEY> BOOL 
AL_TreeAVLSeq<T, KEY>::IsFull() const
{
	return (m_dwMaxSize <= GetNodesNum()) ? TRUE:FALSE;
}
#endif // CXX_AL_TREEAVLSEQ_H
/* EOF */

测试代码

#ifdef TEST_AL_TREEAVLSEQ
	AL_TreeAVLSeq<DWORD, DWORD> cTreeAVL(100);
	BOOL bEmpty = cTreeAVL.IsEmpty();
	std::cout<<bEmpty<<std::endl;
	const AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pConstRootNode = cTreeAVL.GetRootNode();
	AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pRootNode = const_cast<AL_TreeNodeBinSearchSeq<DWORD, DWORD>*>(pConstRootNode);
	std::cout<<pRootNode<<std::endl;
	DWORD dwDegree = cTreeAVL.GetDegree();
	std::cout<<dwDegree<<std::endl;
	DWORD dwHeight = cTreeAVL.GetHeight();
	std::cout<<dwHeight<<std::endl;
	DWORD dwNodesNum = cTreeAVL.GetNodesNum();
	std::cout<<dwNodesNum<<std::endl;

	//insert data
	struct TestData 
	{
		DWORD dwData;
		DWORD dwKey;
	};
	DWORD dwData = 0x00;
	DWORD dwKey = 0x00;
	AL_ListSeq<DWORD> listKey;
	TestData sTestData0_99;
//	srand((int)time(NULL));
	for (DWORD dwTestDataCnt=0x00; dwTestDataCnt<500; dwTestDataCnt++) {
		sTestData0_99.dwKey = rand()%100;
		if (FALSE == cTreeAVL.Get(sTestData0_99.dwKey, dwData)) {
			if (FALSE == cTreeAVL.Insert(sTestData0_99.dwData, sTestData0_99.dwKey)) {
				std::cout<<"*************************Failed Insert The Key:"<<sTestData0_99.dwKey<<"*************************"<<std::endl;
			}
			else {
				listKey.InsertEnd(sTestData0_99.dwKey);
				if (FALSE == cTreeAVL.IsBalancedTreeBin()) {
					std::cout<<"*************************Failed Insert The Key:"<<dwKey<<"*************************"<<std::endl;
				}
				for (DWORD dwKeyCnt=0x00; dwKeyCnt<listKey.Length(); dwKeyCnt++) {
					if (TRUE == listKey.Get(dwKeyCnt, dwKey)) {
						if (FALSE == cTreeAVL.Get(dwKey, dwData)) {
							std::cout<<"*************************Failed Insert The Key:"<<dwKey<<"*************************"<<std::endl;
						}
					}
				}
			}
		}
	}
	TestData sTestDataMakeSure0_99;
	for (DWORD dwTestDataCnt=0x00; dwTestDataCnt<100; dwTestDataCnt++) {
		if (FALSE == cTreeAVL.Get(dwTestDataCnt, dwData)) {
			sTestDataMakeSure0_99.dwKey = dwTestDataCnt;
			if (FALSE == cTreeAVL.Insert(sTestDataMakeSure0_99.dwData, sTestDataMakeSure0_99.dwKey)) {
				std::cout<<"*************************Failed Insert The Key:"<<dwTestDataCnt<<"*************************"<<std::endl;
			}
			else {
				listKey.InsertEnd(sTestDataMakeSure0_99.dwKey);
				if (FALSE == cTreeAVL.IsBalancedTreeBin()) {
					std::cout<<"*************************Failed Insert The Key:"<<dwKey<<"*************************"<<std::endl;
				}
				for (DWORD dwKeyCnt=0x00; dwKeyCnt<listKey.Length(); dwKeyCnt++) {
					if (TRUE == listKey.Get(dwKeyCnt, dwKey)) {
						if (FALSE == cTreeAVL.Get(dwKey, dwData)) {
							std::cout<<"*************************Failed Insert The Key:"<<dwKey<<"*************************"<<std::endl;
						}
					}
				}
			}
		}
	}
	cTreeAVL.Print();
	
	BOOL bGet = cTreeAVL.Get(23, dwData);
	std::cout<<bGet<<", "<<dwData<<std::endl;

	pConstRootNode = cTreeAVL.GetRootNode();
	pRootNode = const_cast<AL_TreeNodeBinSearchSeq<DWORD, DWORD>*>(pConstRootNode);
	std::cout<<pRootNode<<std::endl;

	const AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pConstTreeNode = cTreeAVL.GetChildNodeLeftAtNode(pRootNode);
	AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pTreeNode = const_cast<AL_TreeNodeBinSearchSeq<DWORD, DWORD>*>(pConstTreeNode);
	std::cout<<pTreeNode<<std::endl;

	const AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pConstTreeNode20 = cTreeAVL.GetChildNodeLeftAtNode(pTreeNode);
	AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pTreeNode20 = const_cast<AL_TreeNodeBinSearchSeq<DWORD, DWORD>*>(pConstTreeNode20);
	std::cout<<pTreeNode<<std::endl;

	const AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pConstTreeNode31 = cTreeAVL.GetChildNodeRightAtNode(pConstTreeNode20);
	AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pTreeNode31 = const_cast<AL_TreeNodeBinSearchSeq<DWORD, DWORD>*>(pConstTreeNode31);

	const AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pConstTreeNode30 = cTreeAVL.GetChildNodeLeftAtNode(pConstTreeNode20);
	AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pTreeNode30 = const_cast<AL_TreeNodeBinSearchSeq<DWORD, DWORD>*>(pConstTreeNode30);

	const AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pConstTreeNode999 = cTreeAVL.GetChildNodeRightAtNode(pConstTreeNode30);
	AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pTreeNode999 = const_cast<AL_TreeNodeBinSearchSeq<DWORD, DWORD>*>(pConstTreeNode999);


	const AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pConstTreeNode41 = cTreeAVL.GetChildNodeRightAtNode(pConstTreeNode31);
	AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pTreeNode41 = const_cast<AL_TreeNodeBinSearchSeq<DWORD, DWORD>*>(pConstTreeNode41);

	const AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pConstTreeNode33 = cTreeAVL.GetChildNodeRightAtNode(pTreeNode20);
	AL_TreeNodeBinSearchSeq<DWORD, DWORD>* pTreeNode33 = const_cast<AL_TreeNodeBinSearchSeq<DWORD, 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_TreeNodeBinSearchSeq<DWORD, DWORD>*	pChild = NULL;
	pChild = cTreeAVL.GetChildNodeRightAtNode(pTreeNode);
	if (NULL != pChild) {
		std::cout<<pChild->GetLevel()<<"    "<<pChild->GetData()<<"    "<<pChild->GetDegree()<<std::endl;
		std::cout<<pChild->IsLeaf()<<"    "<<pChild->IsBranch()<<"    "<<pChild->IsParent(pTreeNode)<<"    "<<pChild->IsParent(pTreeNode33)<<std::endl;
	}
	pChild = cTreeAVL.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 = cTreeAVL.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 = cTreeAVL.GetChildNodeRightAtNode(pTreeNode);
	if (NULL != pChild) {
		std::cout<<pChild->GetLevel()<<"    "<<pChild->GetData()<<"    "<<pChild->GetDegree()<<std::endl;
		std::cout<<pChild->IsLeaf()<<"    "<<pChild->IsBranch()<<"    "<<pChild->IsParent(pTreeNode)<<"    "<<pChild->IsParent(pTreeNode33)<<std::endl;
	}
	pChild = cTreeAVL.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 = cTreeAVL.IsEmpty();
	std::cout<<bEmpty<<std::endl;
	dwDegree = cTreeAVL.GetDegree();
	std::cout<<dwDegree<<std::endl;
	dwHeight = cTreeAVL.GetHeight();
	std::cout<<dwHeight<<std::endl;
	dwNodesNum = cTreeAVL.GetNodesNum();
	std::cout<<dwNodesNum<<std::endl;

	AL_ListSeq<DWORD> cListData;
	AL_ListSeq<DWORD> cListKey;
	BOOL bSibling = cTreeAVL.GetSiblingAtNode(pTreeNode, cListData, cListKey);
	if (TRUE == bSibling) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();

	bSibling = cTreeAVL.GetSiblingAtNode(pTreeNode20, cListData, cListKey);
	if (TRUE == bSibling) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();


	BOOL bAncestor = cTreeAVL.GetAncestorAtNode(pRootNode, cListData, cListKey);
	if (TRUE == bAncestor) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}

	bAncestor = cTreeAVL.GetAncestorAtNode(pTreeNode33, cListData, cListKey);
	if (TRUE == bAncestor) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();

	BOOL bDescendant = cTreeAVL.GetDescendantAtNode(pRootNode, cListData, cListKey);
	if (TRUE == bDescendant) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();

	bDescendant = cTreeAVL.GetDescendantAtNode(pTreeNode33, cListData, cListKey);
	if (TRUE == bDescendant) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();

	BOOL bOrder = cTreeAVL.PreOrderTraversal(cListData, cListKey);
	if (TRUE == bOrder) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();

	bOrder = cTreeAVL.InOrderTraversal(cListData, cListKey);
	if (TRUE == bOrder) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();

	bOrder = cTreeAVL.PostOrderTraversal(cListData, cListKey);
	if (TRUE == bOrder) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();

	bOrder = cTreeAVL.LevelOrderTraversal(cListData, cListKey);
	if (TRUE == bOrder) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();

	//	cTreeAVL.Remove(pTreeNode20);
	bOrder = cTreeAVL.LevelOrderTraversal(cListData, cListKey);
	if (TRUE == bOrder) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();
	bEmpty = cTreeAVL.IsEmpty();
	std::cout<<bEmpty<<std::endl;
	dwDegree = cTreeAVL.GetDegree();
	std::cout<<dwDegree<<std::endl;
	dwHeight = cTreeAVL.GetHeight();
	std::cout<<dwHeight<<std::endl;
	dwNodesNum = cTreeAVL.GetNodesNum();
	std::cout<<dwNodesNum<<std::endl;

	BOOL bRemoveNode = cTreeAVL.RemoveNode(66);
	std::cout<<bRemoveNode<<std::endl;
	bOrder = cTreeAVL.LevelOrderTraversal(cListData, cListKey);
	if (TRUE == bOrder) {
		for (DWORD dwCnt=0; dwCnt<cListData.Length(); dwCnt++) {
			if (TRUE == cListData.Get(dwCnt, dwData) && TRUE == cListKey.Get(dwCnt, dwKey)) {
				std::cout<<"["<<dwData<<", "<<dwKey<<"]"<<", ";
			}
		}	
		std::cout<<std::endl;
	}
	cListData.Clear();

	BOOL bRemove = cTreeAVL.Remove(65);
	std::cout<<bRemove<<std::endl;
	bEmpty = cTreeAVL.IsEmpty();
	std::cout<<bEmpty<<std::endl;
	pConstRootNode = cTreeAVL.GetRootNode();
	pRootNode = const_cast<AL_TreeNodeBinSearchSeq<DWORD, DWORD>*>(pConstRootNode);
	std::cout<<pRootNode<<std::endl;
	dwDegree = cTreeAVL.GetDegree();
	std::cout<<dwDegree<<std::endl;
	dwHeight = cTreeAVL.GetHeight();
	std::cout<<dwHeight<<std::endl;
	dwNodesNum = cTreeAVL.GetNodesNum();
	std::cout<<dwNodesNum<<std::endl;
#endif

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/xiaoting451292510/article/details/17606115
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞