二叉树,先回顾下二叉树的特点:
关于二叉树;n总=n0+n1+n2;n0=n2 + 1 ;so…n总=n1+2*n2+1
每层的最大结点数2^(n-1); 结点总数最大是2^n - 1
关于遍历:先序是:根左右;
中序是:左根右;
后序是:左右根;
一般我们会选择递归的方法来遍历这样代码回简单些;这题也是一样的。
但由于已经给出了函数的框架,所以代码回收到限制;
思路还是递归,方法是分段递归;
/* struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; TreeNode *root;*/ class Solution { public: struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) { //判定递归终止条件; if(pre.size() == 0 || in.size() == 0) { return NULL; } //定义Node节点并其求根节点; int root = pre[0]; TreeNode* node = new TreeNode(root); vector<int>::iterator it; //求左右子树的遍历序列; vector<int> preLeft, preRight, inLeft, inRight; //1、求根节点在中序遍历序列中的位置; vector<int>::iterator i; for(it = in.begin(); it != in.end(); it++) { if(root == *it) { i = it; } } //2、求左右子树的中序遍历子序列; int k = 0; for(it = in.begin(); it != in.end(); it++) { if(k == 0) inLeft.push_back(*it); else if(k == 1) inRight.push_back(*it); if(it == i) k = 1; } //3、求左右子树的前序遍历子序列; k = 0; vector<int>::iterator ite; for(it = pre.begin()+1; it != pre.end(); it++) { for(ite = inLeft.begin(); ite != inLeft.end(); ite++) { if(*it == *ite) { preLeft.push_back(*it); k = 1; } } if(k == 0) { preRight.push_back(*it); } k = 0; } //根据遍历序列求出跟的左右节点; node->left = reConstructBinaryTree(preLeft,inLeft); node->right = reConstructBinaryTree(preRight,inRight); //返回节点地址; return node; } };
学会了方法可以在HDUOJ上做一个,练习一下;
题意是:已知先序和中序输出二叉树的后序!
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1710
249ms AC
#include<stdio.h> #include<vector> using namespace std; struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; TreeNode *root; class Solution { public: struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) { //判定递归终止条件; if(pre.size() == 0 || in.size() == 0) { return NULL; } //定义Node节点并其求根节点; int root = pre[0]; TreeNode* node = new TreeNode(root); vector<int>::iterator it; //求左右子树的遍历序列; vector<int> preLeft, preRight, inLeft, inRight; //1、求根节点在中序遍历序列中的位置; vector<int>::iterator i; for(it = in.begin(); it != in.end(); it++) { if(root == *it) { i = it; } } //2、求左右子树的中序遍历子序列; int k = 0; for(it = in.begin(); it != in.end(); it++) { if(k == 0) inLeft.push_back(*it); else if(k == 1) inRight.push_back(*it); if(it == i) k = 1; } //3、求左右子树的前序遍历子序列; k = 0; vector<int>::iterator ite; for(it = pre.begin()+1; it != pre.end(); it++) { for(ite = inLeft.begin(); ite != inLeft.end(); ite++) { if(*it == *ite) { preLeft.push_back(*it); k = 1; } } if(k == 0) { preRight.push_back(*it); } k = 0; } //根据遍历序列求出跟的左右节点; node->left = reConstructBinaryTree(preLeft,inLeft); node->right = reConstructBinaryTree(preRight,inRight); //返回节点地址; return node; } }; /***后序遍历***左右根***/ void posOrderRecur(TreeNode *head){ if(head==NULL) return ; posOrderRecur(head->left); posOrderRecur(head->right); if(head==root) printf("%d\n",head->val); else printf("%d ",head->val); } int main() { int n; Solution so; while(scanf("%d",&n)>0) { root=new TreeNode(NULL); vector<int> a,b; int x; for(int i=0;i<n;i++) { scanf("%d",&x); a.push_back(x); } for(int i=0;i<n;i++) { scanf("%d",&x); b.push_back(x); } root=so.reConstructBinaryTree(a,b); TreeNode *h=root; posOrderRecur(h); } return 0; }
然后在提供一种数组递归的,利用指针,会方便很多呢。
46ms AC
#include<stdio.h> #include<vector> using namespace std; struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; TreeNode *root; TreeNode *Creat(int *pre,int *in,int n) { TreeNode *s; for(int i=0;i<n;i++) { if(pre[0]==in[i]) { s=new TreeNode(in[i]); //中序历遍中在根节点左边的都是左子树上的 s->left=Creat(pre+1,in,i); //在根节点右边的,都是右子树上的,右子树需要从i+1开始 s->right=Creat(pre+i+1,in+i+1,n-i-1); return s; } } return NULL; } /***后序遍历***左右根***/ void posOrderRecur(TreeNode *head){ if(head==NULL) return ; posOrderRecur(head->left); posOrderRecur(head->right); if(head==root) printf("%d\n",head->val); else printf("%d ",head->val); } int main() { int n; while(scanf("%d",&n)!=EOF) { root=NULL; int a[2005],b[2005]; for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) scanf("%d",&b[i]); root=Creat(a,b,n); TreeNode *head=root; posOrderRecur(head); } return 0; }