二叉樹(14)----由前序遍歷和中序遍歷重建二叉樹,遞迴方式
阿新 • • 發佈:2019-01-27
相關連結:
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; }