1. 程式人生 > >二叉樹(14)----由前序遍歷和中序遍歷重建二叉樹,遞迴方式

二叉樹(14)----由前序遍歷和中序遍歷重建二叉樹,遞迴方式

相關連結:

1、二叉樹定義

typedef struct BTreeNodeElement_t_ {
    void *data;
} BTreeNodeElement_t;


typedef struct BTreeNode_t_ {
    BTreeNodeElement_t     *m_pElemt;
    struct BTreeNode_t_    *m_pLeft;
    struct BTreeNode_t_    *m_pRight;
} BTreeNode_t;

二、根據前序遍歷序列和中序遍歷序列重建二叉樹

演算法說明:

由中序遍歷序列可知,第一個節點是根節點,

由前序遍歷序列可知,第一個節點是根節點的左子樹節點,而且前序遍歷中,根節點左邊是左子樹,右邊是右子樹,因此通過中序遍歷的根節點可以確定的是:

    根節點在前序遍歷中的位置(通過遍歷前序遍歷序列,比較每一個節點與中序遍歷中的第一個節點即根節點可知);

    左子樹的節點數,因為一旦找到前序遍歷中根節點的位置,就找到左右子樹的分界點,也就是說,前序遍歷中根節點左邊的都是左子樹節點,可以通過遍歷知道左子樹的節點數;

    同樣,右子樹的節點數也可以確定。

通過以上確定的資訊,可以劃分出前序遍歷中的左右子樹節點數,根節點位置;因此,下面就是進行求根節點左節點和右節點,而根據上述劃分,可以知道左子樹前序和中序序列起始位置以及長度、右子樹前序和中序序列起始位置以及長度,這樣可以遞迴按照上述方式同樣獲得左右子樹的根節點。

通過遞迴可以求得整個樹的結構。

BTreeNode_t  * RebuildBTree( const BTreeNodeElement_t *pPreorder,  
                             const BTreeNodeElement_t *pInorder, 
                             const int nodesTotal, 
                             int(*compare)(const BTreeNodeElement_t*, const BTreeNodeElement_t *)){
    if( pPreoder == NULL || pInorder == NULL || nodesTotal <= 0 || compare == NULL)
        return NULL;

    BTreeNodeElement_t *pRootData = &pInorder[0];  //找到當前樹的根節點
    BTreeNode_t *pRoot= new  BTreeNode_t;
    pRoot->m_pElemt = pRootData;

    int rootIndex = -1;
    for( int i = 0; i < nodesTotal; ++i){
        if( compare( pRootData, &pPreorder[i]) == 0){
            rootIndex = i;
            brea;
        }
    }
    if( rootIndex == -1 )
        return NULL;

//根據查詢到根節點得到的資訊,左子樹長度,右子樹長度等
    int leftNodesTotal = rootIndex;
    BTreeNodeElement_t *pLeftPreorder = pPreorder + 1;
    BTreeNodeElement_t *pLeftInorder = pInorder;
    pRoot->m_pLeft = RebuildBTree( pLeftPreorder, pInorder, leftNodesTotal, compare);

//右子樹資訊
    int rightNodesTotal = nodesTotal - leftNodesTotal - 1;//減去右子樹節點數和一個根節點
    BTreeNodeElement_t *pRightPreOrder = pPreorder + leftNodesTotal + 1;
    BTreeNodeElement_t *pRightInorder = pInorder + leftNodesTotal + 1;
    pRoot->m_pRight = RebuildBTree( pRightPreOrder, pRightInorder, rightNodesTotal, compare);

    return pRoot;
}