プログラミングの美しさ--ツリーの再構築
次のように、前の順序と中の順序の結果を指定します.
前順: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を繰り返すことに相当する.再帰的に解決できることがわかります.
具体的には、直接コードを貼り付けました(ネット上を参照):
前順: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));
}
}