プログラミングの美しさ--ツリーの再構築


次のように、前の順序と中の順序の結果を指定します.
前順:a b d c e f
中序:d b a e c f
この二叉木を再建する.
考え方と手順:
1.最初のノードは、必ず再構築するツリーのルートノードです.例えばaは現在のシーケンスのルートノードである.
2.中順シーケンスでaノードを見つけ、中順遍歴結果を2つのシーケンスに分け、左側はaの左サブツリーd b、右側はaの右サブツリーe c fである.同時に前系列も左サブツリー系列と右サブツリー系列に分ける.
3.aの左サブツリーと右サブツリーをそれぞれ再構築し、(b d,d b)(c e f,e c f)は、ステップ1を繰り返すことに相当する.再帰的に解決できることがわかります.
具体的には、直接コードを貼り付けました(ネット上を参照):
struct NODE 
{
    NODE *pLeft;
    NODE *pRight;
    char chValue;
};

int  CharInStrFirstPos(char ch, char *str, int nLen)
{
    char *pOrgStr = str;
    while (nLen > 0 && ch != *str)
    {
        str++;
        nLen--;
    }
    
    return (nLen > 0) ? (str - pOrgStr) : -1;
}

void ReBuild_PreIn(char *pPreOrder, char *pInOrder, int nTreeLen, NODE **pRoot)
{
    if (pPreOrder == NULL || pInOrder == NULL)
    {
        return;
    }

    NODE *pTemp = new NODE;
    pTemp->chValue = *pPreOrder;
    pTemp->pLeft = NULL;
    pTemp->pRight = NULL;

    if (*pRoot == NULL)
    {
        *pRoot = pTemp;
    }

    if (nTreeLen == 1)
    {
        return;
    }

    int nLeftLen = CharInStrFirstPos(*pPreOrder, pInOrder, nTreeLen);
    assert(nLeftLen != -1);
    int nRightLen = nTreeLen - nLeftLen -1;

    if (nLeftLen > 0)
    {
        ReBuild_PreIn(pPreOrder + 1, pInOrder, nLeftLen, &((*pRoot)->pLeft));
    }

    if (nRightLen > 0)
    {
        ReBuild_PreIn(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen + 1,
            nRightLen, &((*pRoot)->pRight));
    }
}