1. 程式人生 > >B+Tree模板改進版0.51版——可獨立編譯,修改了錯誤

B+Tree模板改進版0.51版——可獨立編譯,修改了錯誤

       最近應網友的要求,仔細檢查和修改了B+Tree的模板類,修正了幾處錯誤,主要是刪除Key的引數錯誤,同時去掉了那個標頭檔案的包含,直接將標頭檔案的內容貼在了檔案開頭處,以使此模板類可以獨立使用。

       註釋掉的顯示到樹控制元件中的方法,可以在使用MFC的CTreeCtrl情況下自行恢復即可,這樣就可以將整個B+Tree顯示到樹控制元件中,方便只管的觀察B+Tree節點的構造。但是因為B+Tree結構的特殊性,所以在檢視時可能需要花些心思來分析。

#include <tchar.h>
#define WIN32_LEAN_AND_MEAN //在windows.h中排除單獨引用的APIs,比如WinSock的API
#include <windows.h>
#pragma once
#define GRSPOSITION void*
//==========================================================
//TRank 表示每個節點中的階數,則節點中的Key數目是2*TRank
//指向下級的指標數目是 2*TRank + 1,同時Key和Data是一對一的
//要求Key型別必須有 > 運算子
//實際使用中最好為TKey和TData型別過載 = 運算子
//==========================================================
template <class TKey,class TData,INT TRank>
class CGRSBTreeNode
{
public:
    INT m_nCnt;    //當前節點中的Key個數
    TKey  m_Key [2 * TRank]; //Key陣列
    TData m_Data[2 * TRank];    //Data陣列

    CGRSBTreeNode<TKey,TData,TRank>* m_pChild[ 2 * TRank + 1 ]; //指向孩子的指標陣列
public:
    CGRSBTreeNode()
        :m_nCnt(0)
    {
        ::ZeroMemory(m_Key, 2 * TRank * sizeof(TKey));
        ::ZeroMemory(m_Data,2 * TRank * sizeof(TData));
        ::ZeroMemory(m_pChild,( 2 * TRank + 1) * sizeof(CGRSBTreeNode<TKey,TData,TRank>*));
    }
};


template <class TKey,class TData,INT TRank = 10>
class CGRSBTree
{
protected:
    CGRSBTreeNode<TKey,TData,TRank>* m_pRoot; //樹根節點
    INT  m_iHeight;        //樹高度
    INT m_nKeyCnt;        //鍵總數
    INT m_nNodeCnt;       //節點總數
protected:
    INT m_nSearchIndex;       // 查詢時找到的鍵在節點中的位置

    TData m_InsData;        // 與要插的鍵相對應的值
    TKey m_InsKey;        /// 要插入的鍵

    INT  m_iAccessLevel;       // 當前訪問的節點所處的高度
    CGRSBTreeNode<TKey,TData,TRank>* m_pNewNode; // 在節點分割的時候指向新建的節點

    BOOL m_bFlag;         // 節點增減標誌
public:
    CGRSBTree()
        :m_iHeight(0)
        ,m_nKeyCnt(0)
        ,m_nNodeCnt(0)
        ,m_nSearchIndex(0)
        ,m_iAccessLevel(0)
        ,m_pNewNode(NULL)
        ,m_bFlag(FALSE)
    {
        //申請一個0節點的樹根
        m_pRoot = NULL;
    }

    virtual ~CGRSBTree()
    {
    }

protected:
    void Insert(CGRSBTreeNode<TKey,TData,TRank>*& pNode,const TKey& Key,const TData& Data)
    {
        INT i = 0;
        INT j = 0;
        INT k = 0;

        m_iAccessLevel --;

        if ( m_iAccessLevel < 0 )
        {
            m_pNewNode = NULL;
            m_InsKey = Key;
            m_InsData = Data;
            m_nKeyCnt ++;
            m_bFlag = TRUE;
            //pNode = NewNode(pNode,Key,Data);
            return;
        }


        for(i = 0, j = pNode->m_nCnt - 1;
            i < j;
            k= ( j + i) / 2, ( Key > pNode-> m_Key[k])?( i = k + 1 ):( j = k ));

        if ( Key == pNode-> m_Key[ i ] )
        {
            Error(1,Key); /* 鍵已經在樹中 */
            m_bFlag = FALSE;
            return;
        }

        if ( Key > pNode-> m_Key[ i ] )
        {/* i == pNode->m_nCnt - 1 時有可能出現 */
            i ++;
        }

        //向孩子節點插入
        Insert( pNode -> m_pChild[ i ] , Key, Data );

        if ( FALSE == m_bFlag )
        {
            return;
        }

        /* 有新鍵要插入到當前節點中 */
        if ( pNode->m_nCnt < 2 * TRank )
        {/* 當前節點未滿 */
            InsertAt( pNode, i ,Key,Data); /* 把鍵值+子樹對插入當前節點中 */
            m_bFlag = FALSE; /* 指示上層節點沒有需要插入的鍵值+子樹,插入過程結束 */
        }
        else
        {/* 當前節點已滿,則分割這個頁面並把鍵值+子樹對插入當前節點中 */
            SplitNode(pNode, i); /* 繼續指示上層節點把返回的鍵值+子樹插入其中 */
        }
    }

    /*
    * 把一個鍵和對應的右子樹插入一個節點中
    */
    void InsertAt(CGRSBTreeNode<TKey,TData,TRank>* pNode, INT nIndex,const TKey& Key,const TData& Data)
    {
        int i = 0;
        /* 把所有大於要插入的鍵值的鍵和對應的右子樹右移 */
        for(i = pNode->m_nCnt; i > nIndex; i--)
        {
            pNode-> m_Key[ i ]  = pNode-> m_Key[i-1];
            pNode-> m_Data[ i ]  = pNode-> m_Data[i-1];
            pNode-> m_pChild[i+1] = pNode-> m_pChild[ i ];
        }

        /* 插入鍵和右子樹 */
        pNode-> m_Key[ i ]  = Key;
        pNode-> m_Data[ i ]  = Data;
        pNode-> m_pChild[ i + 1 ] = m_pNewNode;
        pNode-> m_nCnt ++;
    }

    /*
    * 前件是要插入一個鍵和對應的右子樹,並且本節點已經滿
    * 導致分割這個節點,插入鍵和對應的右子樹,
    * 並向上層返回一個要插入鍵和對應的右子樹
    */
    void SplitNode( CGRSBTreeNode<TKey,TData,TRank>*& pNode, INT nIndex )
    {    
        INT i = 0;
        INT j = 0;
        CGRSBTreeNode<TKey,TData,TRank>* pTmpNode = NULL;
        TKey tmpKey;
        TData tmpData;
        /* 建立新節點 */
        pTmpNode = new CGRSBTreeNode<TKey,TData,TRank>();
        /*
        *   +---+--------+-----------+---------+--------+---------+
        *   | 0 | ...... |  TRank    | TRank+1 | ...... |2*TRank-1|
        *   +---+--------+-----------+---------+--------+---------+
        *   |<-      TRank+1       ->|<-        TRank-1         ->|  
        */

        if ( nIndex > TRank )
        {//要插入當前節點的右半部分
            //把從 2*TRank-1 到 TRank+1 的 TRank-1 個鍵值+子樹對轉移到新節點中,
            //並且為要插入的鍵值+子樹空出位置
            for( i = 2 * TRank - 1, j = TRank - 1; i >= nIndex; i --,j --)
            {
                pTmpNode-> m_Key[j]    = pNode-> m_Key[ i ];
                pTmpNode-> m_Data[j]   = pNode-> m_Data[ i ];
                pTmpNode-> m_pChild[ j + 1 ] = pNode-> m_pChild[i + 1];
            }

            for(i = nIndex - 1, j = nIndex - TRank - 2; j >= 0; i--,j--)
            {
                pTmpNode-> m_Key[j]    = pNode-> m_Key[ i ];
                pTmpNode-> m_Data[j]   = pNode-> m_Data[ i ];
                pTmpNode-> m_pChild[ j + 1 ] = pNode-> m_pChild[i + 1];
            }

            //把節點的最右子樹轉移成新節點的最左子樹
            pTmpNode-> m_pChild[0] = pNode-> m_pChild[ TRank + 1 ];

            //在新節點中插入鍵和右子樹
            pTmpNode-> m_Key[ nIndex - TRank - 1] = m_InsKey;
            pTmpNode-> m_Data[ nIndex - TRank - 1] = m_InsData;
            pTmpNode-> m_pChild[ nIndex - TRank ] = m_pNewNode;

            //設定要插入上層節點的鍵和值
            m_InsKey = pNode-> m_Key[TRank];
            m_InsData = pNode-> m_Data[TRank];

            //tmpKey  = pNode->m_Key[TRank];
            //tmpData = pNode->m_Data[TRank];
        }
        else
        { /* nIndex <= TRank */
            /* 把從 2*TRank-1 到 TRank 的 TRank 個鍵值+子樹對轉移到新節點中 */
            for( i = 2 * TRank - 1,j = TRank - 1; j >= 0; i--,j--)
            {
                pTmpNode-> m_Key[j]   = pNode-> m_Key[ i ];
                pTmpNode-> m_Data[j]  = pNode-> m_Data[ i ];
                pTmpNode-> m_pChild[j + 1] = pNode-> m_pChild[ i + 1 ];
            }

            if (nIndex == TRank)
            {
                pTmpNode-> m_pChild[0] = m_pNewNode;
            }
            else
            { /* (nIndex<TRank) 要插入當前節點的左半部分 */
                /* 把節點當前的最右子樹轉移成新節點的最左子樹 */
                pTmpNode-> m_pChild[0] = pNode-> m_pChild[ TRank ];
                /* 儲存要插入上層節點的鍵和值 */
                tmpKey = pNode-> m_Key[ TRank - 1];
                tmpData = pNode-> m_Data[ TRank - 1];

                /* 把所有大於要插入的鍵值的鍵和對應的右子樹右移 */
                for(i = TRank - 1; i > nIndex; i --)
                {
                    pNode-> m_Key[ i ]   = pNode-> m_Key[i-1];
                    pNode-> m_Data[ i ]   = pNode-> m_Data[i - 1];
                    pNode-> m_pChild[ i + 1 ] = pNode-> m_pChild[ i ];
                }

                pNode-> m_Key[nIndex]  = m_InsKey;
                pNode-> m_Data[nIndex]  = m_InsData;

                pNode-> m_pChild[nIndex+1] = m_pNewNode;

                m_InsKey = tmpKey;
                m_InsData = tmpData;
            }
        }

        pNode->m_nCnt = TRank;
        pTmpNode->m_nCnt= TRank;
        m_pNewNode  = pTmpNode;
        m_nNodeCnt ++;

        //pNode = NewNode(pNode,tmpKey,tmpData);
    }


    void Remove( CGRSBTreeNode<TKey,TData,TRank>* pNode,const TKey& Key,TData& Data)
    {
        INT i = 0;
        INT j = 0;
        INT k = 0;
        CGRSBTreeNode<TKey,TData,TRank>* pLeft = NULL;
        CGRSBTreeNode<TKey,TData,TRank>* pRight = NULL;
        INT nTmpLevel = 0;

        m_iAccessLevel -- ;

        if ( m_iAccessLevel < 0 )
        {
            Error(0,Key); /* 在整個樹中未找到要刪除的鍵 */
            m_bFlag = FALSE;
            return;
        }

        for(i=0, j = pNode->m_nCnt - 1;
            i < j;
            k=( j + i ) / 2, ( Key > pNode-> m_Key[k] ) ? (i = k + 1):( j = k ));

        if ( Key == pNode-> m_Key[ i ] )
        { /* 找到要刪除的鍵 */
            Data = pNode-> m_Data[ i ];

            if (m_iAccessLevel == 0)
            { 
                DelFromNode(pNode,i);

                m_nKeyCnt -- ;
                m_bFlag = TRUE;
                return;
            }
            else
            { /* 這個鍵位於非葉節點 */
                nTmpLevel = m_iAccessLevel - 1;

                /* 找到前驅節點 */
                pRight = pNode-> m_pChild[ i ];

                while (nTmpLevel > 0) 
                {
                    pRight = pRight->m_pChild[pRight->m_nCnt];
                    nTmpLevel--;
                }

                pNode-> m_Key[ i ]  = pRight-> m_Key[pRight->m_nCnt-1];
                pNode-> m_Data[ i ]  = pRight-> m_Data[pRight->m_nCnt-1];
                pRight-> m_Data[pRight->m_nCnt-1] = NULL;
                //Key = pRight-> m_Key[ pRight->m_nCnt - 1 ];
            }
        }
        else if (Key > pNode-> m_Key[ i ])
        {/* i == pNode->m_nCnt-1 時有可能出現 */
            i++;         
        }

        Remove(pNode-> m_pChild[ i ], Key , Data );

        /* 調整平衡 */
        if ( FALSE == m_bFlag )
        {
            return;
        }

        if (pNode-> m_pChild[ i ]->m_nCnt < TRank)
        {
            if (i == pNode->m_nCnt)
            {/* 在最右子樹中發生了刪除 */
                i--; /* 調整最右鍵的左右子樹平衡 */
            }

            pLeft = pNode-> m_pChild [ i ];
            pRight = pNode-> m_pChild[i+1];

            if (pRight->m_nCnt > TRank)
            {
                MoveLeftNode(pNode,i);
            }
            else if(pLeft->m_nCnt > TRank)
            {
                MoveRightNode(pNode,i);
            }
            else
            {
                JoinNode(pNode,i);
                /* 繼續指示上層節點本子樹的鍵數量減少 */
                return;
            }

            m_bFlag = FALSE;
            /* 指示上層節點本子樹的鍵數量沒有減少,刪除過程結束 */
        }
    }

    /*
    * 合併一個節點的某個鍵對應的兩個子樹
    */
    void JoinNode(CGRSBTreeNode<TKey,TData,TRank>* pNode, INT nIndex)
    {
        CGRSBTreeNode<TKey,TData,TRank>* pLeft = NULL;
        CGRSBTreeNode<TKey,TData,TRank>* pRight = NULL;
        INT i = 0;
        INT j = 0;

        pLeft = pNode-> m_pChild[nIndex];
        pRight = pNode-> m_pChild[nIndex + 1];

        /* 把這個鍵下移到它的左子樹 */
        pLeft-> m_Key[pLeft->m_nCnt] = pNode-> m_Key[nIndex];
        pLeft-> m_Data[pLeft->m_nCnt] = pNode-> m_Data[nIndex];

        /* 把右子樹中的所有鍵值和子樹轉移到左子樹 */
        for (j=pRight->m_nCnt-1,i=pLeft->m_nCnt+pRight->m_nCnt; j >= 0 ; j--,i--)
        {
            pLeft-> m_Key[ i ]  = pRight-> m_Key[j];
            pLeft-> m_Data[ i ]  = pRight-> m_Data[j];
            pLeft-> m_pChild[ i ] = pRight-> m_pChild[j];
        }

        pLeft-> m_pChild[ pLeft->m_nCnt + pRight->m_nCnt + 1 ] = pRight-> m_pChild[ pRight->m_nCnt ];
        pLeft->m_nCnt += pRight->m_nCnt + 1;

        delete pRight;
        /* 把這個鍵右邊的鍵和對應的右子樹左移 */
        for (i=nIndex; i < pNode->m_nCnt-1; i++)
        {
            pNode-> m_Key[ i ] = pNode-> m_Key[i+1];
            pNode-> m_Data[ i ] = pNode-> m_Data[i+1];
            pNode-> m_pChild[i+1] = pNode-> m_pChild[i+2];
        }

        pNode->m_nCnt --;
        m_nNodeCnt --;
    }

    /*
    * 從一個鍵的右子樹向左子樹轉移一些鍵,使兩個子樹平衡
    */

    void MoveLeftNode(CGRSBTreeNode<TKey,TData,TRank>* pNode, INT nIndex)
    {
        CGRSBTreeNode<TKey,TData,TRank>* pLeft = NULL;
        CGRSBTreeNode<TKey,TData,TRank>* pRight = NULL;

        INT k = 0; /* 應轉移的鍵的數目 */
        INT i = 0;
        INT j = 0;

        pLeft  = pNode-> m_pChild[nIndex];
        pRight = pNode-> m_pChild[nIndex + 1];

        k = ( pRight->m_nCnt - pLeft->m_nCnt ) / 2;

        /* 把這個鍵下移到它的左子樹 */
        pLeft-> m_Key[pLeft->m_nCnt] = pNode-> m_Key[nIndex];
        pLeft-> m_Data[pLeft->m_nCnt] = pNode-> m_Data[nIndex];

        /* 把右子樹的最左子樹轉移成左子樹的最右子樹
        * 從右子樹向左子樹移動 k-1 個鍵+子樹對 */
        for (j=k-2,i=pLeft->m_nCnt+k-1; j >= 0; j--,i--)
        {
            pLeft-> m_Key[ i ]  = pRight-> m_Key[j];
            pLeft-> m_Data[ i ]  = pRight-> m_Data[j];
            pLeft-> m_pChild[ i ] = pRight-> m_pChild[j];
        }

        pLeft-> m_pChild[ pLeft->m_nCnt + k ] = pRight-> m_pChild[ k - 1 ];

        /* 把右子樹的最左鍵提升到這個鍵的位置上 */
        pNode-> m_Key[nIndex] = pRight-> m_Key[k-1];
        pNode-> m_Data[nIndex] = pRight-> m_Data[k-1];

        /* 把右子樹中的所有鍵值和子樹左移 k 個位置 */
        pRight-> m_pChild[0] = pRight-> m_pChild[k];

        for (i=0; i<pRight->m_nCnt-k; i++)
        {
            pRight-> m_Key[ i ]  = pRight-> m_Key[ i + k ];
            pRight-> m_Data[ i ] = pRight-> m_Data[ i + k ];
            pRight-> m_pChild[ i ] = pRight-> m_pChild[ i + k ];
        }

        pRight-> m_pChild[ pRight->m_nCnt - k ] = pRight-> m_pChild[pRight->m_nCnt];
        pLeft->m_nCnt += k;
        pRight->m_nCnt -= k;
    }

    /*
    * 從一個鍵的左子樹向右子樹轉移一些鍵,使兩個子樹平衡
    */

    void MoveRightNode( CGRSBTreeNode<TKey,TData,TRank>* pNode, INT nIndex)
    {
        CGRSBTreeNode<TKey,TData,TRank>* pLeft = NULL;
        CGRSBTreeNode<TKey,TData,TRank>* pRight = NULL;

        INT k = 0; /* 應轉移的鍵的數目 */
        INT i = 0;
        INT j = 0;

        pLeft = pNode-> m_pChild[nIndex];
        pRight = pNode-> m_pChild[nIndex + 1];

        k = ( pLeft->m_nCnt - pRight->m_nCnt ) / 2;

        /* 把右子樹中的所有鍵值和子樹右移 k 個位置 */
        pRight-> m_pChild[ pRight->m_nCnt + k ] = pRight-> m_pChild[ pRight->m_nCnt ];

        for ( i = pRight->m_nCnt - 1; i >= 0; i -- )
        {
            pRight-> m_Key[i + k]  = pRight-> m_Key[ i ];
            pRight-> m_Data[i + k]  = pRight-> m_Data[ i ];
            pRight-> m_pChild[ i + k ] = pRight-> m_pChild[ i ];
        }

        /* 把這個鍵下移到它的右子樹 */
        pRight-> m_Key[k - 1] = pNode-> m_Key[nIndex];
        pRight-> m_Data[k - 1] = pNode-> m_Data[nIndex];

        /* 把左子樹的最右子樹轉移成右子樹的最左子樹 */

        pRight-> m_pChild[k-1] = pLeft-> m_pChild[pLeft->m_nCnt];

        /* 從左子樹向右子樹移動 k-1 個鍵+子樹對 */
        for ( i = pLeft->m_nCnt - 1,j = k - 2; j >= 0; j --,i -- )
        {
            pRight-> m_Key[j]  = pLeft-> m_Key[ i ];
            pRight-> m_Data[j]  = pLeft-> m_Data[ i ];
            pRight-> m_pChild[j] = pLeft-> m_pChild[ i ];
        }

        /* 把左子樹的最右鍵提升到這個鍵的位置上 */
        pNode-> m_Key[nIndex] = pLeft-> m_Key[ i ];
        pNode-> m_Data[nIndex] = pLeft-> m_Data[ i ];
        pLeft->m_nCnt -= k;
        pRight->m_nCnt += k;
    }

    /*
    * 把一個鍵和對應的右子樹從一個節點中刪除
    */
    void DelFromNode(CGRSBTreeNode<TKey,TData,TRank>* pNode, INT nIndex)
    {
        INT i = 0;
        /* 把所有大於要刪除的鍵值的鍵左移 */
        for( i = nIndex; i < pNode->m_nCnt - 1; i ++ )
        {
            pNode-> m_Key[ i ] = pNode-> m_Key[i+1];
            pNode-> m_Data[ i ] = pNode-> m_Data[i+1];
        }

        pNode->m_nCnt --;
    }

    /*
    * 建立有兩個子樹和一個鍵的根節點
    */

    CGRSBTreeNode<TKey,TData,TRank>* NewNode(CGRSBTreeNode<TKey,TData,TRank>* pNode,const TKey& Key,const TData& Data)
    {
        CGRSBTreeNode<TKey,TData,TRank>* pTmpNode = NULL;
        pTmpNode = new CGRSBTreeNode<TKey,TData,TRank>();
        pTmpNode-> m_nCnt = 1;
        pTmpNode-> m_pChild[0] = pNode;
        pTmpNode-> m_pChild[1] = m_pNewNode;
        pTmpNode-> m_Key[0]    = Key;
        pTmpNode-> m_Data[0]   = Data;
        m_iHeight ++;
        m_nNodeCnt ++;

        return( pTmpNode );
    }

    /*
    * 釋放根節點,並返回它的最左子樹
    */
    CGRSBTreeNode<TKey,TData,TRank>* FreeNode(CGRSBTreeNode<TKey,TData,TRank>* pNode)
    {
        CGRSBTreeNode<TKey,TData,TRank>* pTmpNode = pNode-> m_pChild[0];
        delete pNode;
        m_iHeight --;
        m_nNodeCnt --;
        return pTmpNode;
    }

    void Error(int f,TKey Key)
    {
        //自定義的出錯處理程式碼
    }

    void DelAll(CGRSBTreeNode<TKey,TData,TRank>* pNode)
    {
        INT i = 0;
        m_iAccessLevel --;

        if ( m_iAccessLevel > 0 )
        {
            for ( i = 0; i <= pNode->m_nCnt ; i ++ )
            {
                DelAll( pNode-> m_pChild[ i ] );
            }
        }

        delete pNode;

    }
public:
    BOOL Add(const TKey& Key,const TData& Data)
    {
        m_iAccessLevel = m_iHeight;

        Insert( m_pRoot, Key, Data );

        if ( m_bFlag )
        {
            m_pRoot = NewNode(m_pRoot,Key,Data);    /* 樹的高度增加 */
        }

        return TRUE;
    }

    BOOL Del( const TKey& Key, TData& Data )
    {
        m_iAccessLevel = m_iHeight;

        Remove( m_pRoot, Key, Data );

        if ( 0 == m_pRoot->m_nCnt )
        {
            m_pRoot = FreeNode( m_pRoot );
        }

        return TRUE;
    }

    INT GetHeight()
    {
        return m_iHeight;
    }

    INT GetKeys()
    {
        return m_nKeyCnt;
    }

    double GetPayload()
    {
        if (m_nNodeCnt==0)
        {
            return 1;
        }
        return (double) m_nKeyCnt / (double)( m_nNodeCnt *( 2 * TRank ) );
    }

    CGRSBTreeNode<TKey,TData,TRank>* Destroy ()
    {    
        m_iAccessLevel = m_iHeight;
        m_iHeight      = 0;

        return Delall(m_pRoot);

    }
public:

    GRSPOSITION Search(const TKey& Key, TData& Data)
    {
        INT i = 0;
        INT j = 0;
        INT k = 0;

        INT nLevel = m_iHeight;

        CGRSBTreeNode<TKey,TData,TRank>* pNode = m_pRoot;

        while ( nLevel >= 0 )
        {
            for( i = 0, j = pNode->m_nCnt - 1;
                i < j;
                k = ( j + i ) / 2, ( Key > pNode->m_Key[ k ] ) ? ( i = k + 1) : ( j = k ) );

            if ( Key == pNode->m_Key [ i ] )
            {//找到
                Data = pNode->m_Data[i];
                return (GRSPOSITION) &pNode->m_Key[i];
            }

            if ( Key > pNode->m_Key [ i ] )
            {//節點在右側
                i ++;
            }

            pNode = pNode->m_pChild[ i ];
            nLevel --; //到下層查詢
        }

        return NULL;
    }

    CGRSBTreeNode<TKey,TData,TRank>* GetRoot()
    {
        return m_pRoot;
    }

    //void Show2Tree(CTreeCtrl*pTree,HTREEITEM hItem,CGRSBTreeNode<TKey,TData,TRank>*pNode)
    //{
    //    if( NULL == pNode )
    //    {
    //        return;
    //    }


    //    HTREEITEM hTmp = NULL;
    //    CString strTmp;

    //    for( INT i = 0; i < pNode->m_nCnt; i ++ )
    //    {
    //        if( 0 == i )
    //        {
    //            hTmp = pTree->InsertItem(_T("Child(Start)"),hItem);
    //            Show2Tree(pTree,hTmp,pNode->m_pChild[0]);
    //        }
    //        strTmp.Format(_T("Key(%d)"),pNode->m_Key[i]);

    //        hTmp = pTree->InsertItem(strTmp,hItem);
    //        Show2Tree(pTree,hTmp,pNode->m_pChild[i+1]);
    //    }
    //}

};