|
前几日从朋友得到几个关于树结构的题目,颇为有趣。 第一道题目:一个二叉树,有三种遍历,前序遍历,中序遍历,后序遍历。已知两种遍历的顺序,求出第三种顺序。如前序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; }
|