|
前几日从朋友得到几个关于树结构的题目,颇为有趣。 第一道题目:一个二叉树,有三种遍历,前序遍历,中序遍历,后序遍历。已知两种遍历的顺序,求出第三种顺序。如前序abc,中序bac,则后序则是bca。当然知道前序和后序不一定能确定中序的顺序。如前序ab,后序则是ba,叶结点b可能是左叶,也可能是右叶。就有了第二道题目 第二道题目:如果是一个N叉树,如果知道前序遍历,后序遍历,则这棵树可能有这种可能的形式。 和树有关的算法一般可以用递归算法。因为子树也是一棵树,和递归思想吻合。这两个程序用到的算法就是递归,关键点就是找出子树的起始位置。程序如下:
/* 得到二叉树的后序输出 */
int GetPostOrder(int n, const int* preorder, const int* inorder, int* postorder)
{
if (n == 1)
{
postorder[0] = preorder[0];
}
else if (n > 1)
{
int i;
for (i=0; i<n; i++)
{
if (inorder[i] == preorder[0])
break;
}
if (i == n) return -1;
GetPostOrder(i, preorder+1, inorder, postorder);
GetPostOrder(n-1-i, preorder+1+i, inorder+i+1, postorder+i);
postorder[n-1] = preorder[0];
}
return 0;
}

/* 得到二叉树的中序输出,由于不唯一,所以子树左优先 */
int GetInOrder(int n, const int* preorder, int* inorder, const int* postorder)
{
if (n == 1)
{
inorder[0] = preorder[0];
}
else if (n > 1)
{
int i;
for (i=0; i<n; i++)
{
if (preorder[1] == postorder[i])
break;
}
if (i == n) return -1;
i++;
GetInOrder(i, preorder+1, inorder, postorder);
inorder[i] = preorder[0];
GetInOrder(n-1-i, preorder+1+i, inorder+i+1, postorder+i);
}
return 0;
}

/* 得到二叉树的前序输出 */
int GetPreOrder(int n, int* preorder, const int* inorder, const int* postorder)
{
if (n == 1)
{
preorder[0] = postorder[n-1];
}
else if (n > 1)
{
int i;
for (i=0; i<n; i++)
{
if (inorder[i] == postorder[n-1])
break;
}
if (i == n) return -1;
preorder[0] = postorder[n-1];
GetPreOrder(i, preorder+1, inorder, postorder);
GetPreOrder(n-1-i, preorder+1+i, inorder+i+1, postorder+i);
}
return 0;
}

/* 得到N叉树可能的子树结构的数目 */
int PsbInOrder(int tsize, int n, const int* preorder, const int* postorder)
{
int ret = 1;
if (n > 1)
{
int i, s, size;
for (i=0,s=1,size=0; i<n-1; i++)
{
if (preorder[s] == postorder[i])
{
ret *= PsbInOrder(tsize, i-s+2, preorder+s, postorder+s-1);
size++;
s = i+2;
}
}
for (i=0; i<size; i++)
{
ret = (tsize-i) * ret / (i+1);
}
}
return ret;
}

int main(void)
{
/*
* ABFEGCDHN (前序)
* FBEGAHDNC (中序)
* FGEBHNDCA (后序)
*/
int i;
int preorder[] = {'A','B','F','E','G','C','D','H','N'};
int inorder[] = {'F','B','E','G','A','H','D','N','C'};
int postorder[] = {'F','G','E','B','H','N','D','C','A'};
int n = sizeof(preorder)/sizeof(int);

/*
* abejkcfghid (前序)
* jkebfghicda (后序)
*/
int p1[] = {'a','b','e','j','k','c','f','g','h','i','d'};
int p2[] = {'j','k','e','b','f','g','h','i','c','d','a'};
int m = sizeof(p1)/sizeof(int);
GetPostOrder(n, preorder, inorder, postorder);
for (i=0; i<sizeof(preorder)/sizeof(int); i++)
printf("%c", (char)postorder[i]);
i = PsbInOrder(13, m, p1, p2);
printf("\n%d\n", i);
return 0;
}

|