標籤:二叉樹 重構二叉樹
題目:輸入某二叉樹的前序走訪和中序遍曆的結果,請重建出該二叉樹。假設輸入的前序走訪和中序遍曆的結果中都不含重複的數字。例如輸入前序走訪序列{1,2,4,7,3,5,6,8}和中序遍曆序列{4,7,2,1,5,3,8,6},則重建出圖2.6所示的二叉樹並輸出它的頭結點。二叉樹結點的定義如下:
struct TreeNode{ ElemType data; TreeNode*left; TreeNode*right;};
分析:前序走訪的第一個數1就是根結點,中序遍曆中1之前的數組成了左子樹,也就是4,7,2是左子樹,1之後的數組成了右子樹,也就是3,8,6是右子樹。對於前序走訪的2,4,7同樣仍然是前序走訪,因此,重建整個數就可以分解成重建左子樹和重建右子樹。左子樹的前序走訪是2,4,7,中序遍曆是4,7,2。依次類推……因此我們可以用遞迴的方法解決此問題。
程式樣本:
#include <stdio.h>#include <stdlib.h>#include <memory.h>typedef int ElemType;typedef struct TreeNode{ElemTypedata; struct TreeNode*left;struct TreeNode*right;}TreeNode, *pTreeNode;pTreeNode ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder){int rootValue = startPreorder[0];pTreeNode BTree = (struct TreeNode *)malloc(sizeof(TreeNode));BTree->data = rootValue;BTree->left = BTree->right = NULL;if(startPreorder == endPreorder){if(startInorder == endInorder && *startPreorder == *startInorder)return BTree;elseputs("Invalid input.\n");}int *rootInorder = startInorder;while(rootInorder <= endInorder && *rootInorder != rootValue)++rootInorder;if(rootInorder == endInorder && *rootInorder != rootValue)puts("Invalid input.\n");int leftLength = rootInorder - startInorder;int *leftPreorderEnd = startPreorder + leftLength;if(leftLength > 0){BTree->left = ConstructCore(startPreorder + 1,leftPreorderEnd, startInorder, rootInorder -1);}if(leftLength < endPreorder - startPreorder){BTree->right = ConstructCore(leftPreorderEnd +1,endPreorder, rootInorder + 1, endInorder);}return BTree;}pTreeNode RebuildTree(int *preorder, int *inorder, int length){pTreeNode BTree;if(preorder == NULL || inorder == NULL || length <= 0)return NULL;return ConstructCore(preorder, preorder+length-1, inorder, inorder+length-1);}intmain(int argc, char **argv){int n, i = 0;int tmp;printf("please input the number of the tree:");scanf("%d",&n);int prearray[n];int inarray[n];printf("please input the preorder of the tree:");do{scanf("%d",&tmp);prearray[i] = tmp;i++;}while(i < n);i = 0;printf("please input the inorder of the tree:");do{scanf("%d", &tmp);inarray[i] = tmp;i++;}while(i < n);printf("the preorder is :\n");for(i = 0; i < n; i++){printf("%d\t",prearray[i]);}putchar('\n');printf("the inorder is :\n");for(i = 0; i < n; i++){printf("%d\t",inarray[i]);}putchar('\n'); RebuildTree(prearray, inarray, n);return 0;}
總結:
1、對於樹的三種遍曆,要牢牢的掌握。
2、分析複雜問題時千萬不要怕麻煩,以後遇到的問題肯定都不是一眼就能看出結果的,如果有思路,不要怕麻煩而不去實現它,切記!