UVa 548 - Tree
这题就是运用了二叉树重建, 以及遍历。
二叉树的遍历:先序遍历,中序遍历,后序遍历
只要有一个中序序列再加上另一个序列就可唯一地重建原来二叉树。
先序遍历就是先访问根节点,然后再先序遍历左子树,最后先序遍历右子树。先序遍历也就是深度优先搜索(DFS)。
进行了二叉树重建之后,只要对这棵二叉树进行搜索, 取得各个路径之和,然后找出最小的那个和即可。
/* 题意:给出中序遍历和后序遍历,求最小路径上(从根到叶的和最小)的叶节点,如果有多个最小路径,输出最小叶节点 思路:建树遍历 7 8 11 3 5 16 12 18 8 3 11 7 16 18 12 5 5 7 12 11 16 18 8 3 */ #include<cstdio> #include<cstring> #include<iostream> #include<string> #include<sstream> #include<algorithm> using namespace std; const int N=10001; int a[N], b[N]; struct node { int v; node* l; node* r; }nodes[N]; int nodeindex; node* newNode() { return &nodes[nodeindex++]; } //返回根节点 node* buildTreeInPost(int len, int* in, int *post) { if(len<=0) return 0; int root=post[len-1]; //这个输出也是dfs顺序的 // cout<<root<<endl; node* nd=newNode(); nd->v=root; int* p=find(in, in+len, root); int left_len=p-in; int right_len=len-left_len-1; nd->l=buildTreeInPost(left_len, in, post); nd->r=buildTreeInPost(right_len, in+left_len+1, post+left_len); return nd; } int leastsum, leastleaf; void dfs(node* root, int sum) { if(!root) return; //cout<<root->v<<endl; sum+=root->v; //叶节点 if(!root->l && !root->r) { if(sum<leastsum || (sum==leastsum && root->v<leastleaf)) { leastsum=sum; leastleaf=root->v; } } if(root->l) dfs(root->l, sum); if(root->r) dfs(root->r, sum); } int main() { string str1, str2; while(getline(cin, str1) && getline(cin, str2)) { istringstream istrstr1(str1); istringstream istrstr2(str2); int i=0; while((istrstr1>>a[i]) && (istrstr2>>b[i])) i++; nodeindex=0; // cout<<"buildTreeInPost"<<endl; node* root=buildTreeInPost(i, a, b); leastleaf=leastsum=100000000; // cout<<"dfs"<<endl; dfs(root, 0); cout<<leastleaf<<endl; } return 0; }
由中序遍历 分别和前序遍历,后序遍历进行建树的方法:
/* 题意:给出中序遍历和后序遍历,求最小路径上(从根到叶的和最小)的叶节点,如果有多个最小路径,输出最小叶节点 思路:建树遍历 in order 7 8 11 3 5 16 12 18 post order 8 3 11 7 16 18 12 5 5 7 12 11 16 18 8 3 pre order 5 7 11 8 3 12 16 18 */ #include<cstdio> #include<cstring> #include<iostream> #include<string> #include<sstream> #include<algorithm> using namespace std; const int N=10001; int a[N], b[N]; struct node { int v; node* l; node* r; }nodes[N]; int nodeindex; node* newNode() { return &nodes[nodeindex++]; } //根据中序和后序建树 //返回根节点 node* buildTreeInPost(int len, int* in, int *post) { if(len<=0) return 0; int root=post[len-1]; //这个输出也是dfs顺序的 cout<<root<<endl; node* nd=newNode(); nd->v=root; int* p=find(in, in+len, root); int left_len=p-in; int right_len=len-left_len-1; nd->l=buildTreeInPost(left_len, in, post); nd->r=buildTreeInPost(right_len, in+left_len+1, post+left_len); return nd; } //根据中序和前序建树 //返回根节点 node* buildTreeInPre(int len, int* in, int* pre) { if(len<=0) return 0; int root=pre[0]; //这个输出也是dfs顺序的 cout<<root<<endl; node* nd=newNode(); nd->v=root; int* p=find(in, in+len, root); int left_len=p-in; int right_len=len-left_len-1; nd->l=buildTreeInPre(left_len, in, pre+1); nd->r=buildTreeInPre(right_len, in+left_len+1, pre+left_len+1); return nd; } void dfs(node* root, int sum) { if(!root) return; cout<<root->v<<endl; //叶节点 if(!root->l && !root->r) { return; } if(root->l) dfs(root->l, sum); if(root->r) dfs(root->r, sum); } int main() { string str1, str2; while(getline(cin, str1) && getline(cin, str2)) { istringstream istrstr1(str1); istringstream istrstr2(str2); int i=0; while((istrstr1>>a[i]) && (istrstr2>>b[i])) i++; nodeindex=0; #if 0 // cout<<"buildTreeInPost"<<endl; node* root=buildTreeInPost(i, a, b); #else cout<<"buildTreeInPre"<<endl; node* root=buildTreeInPre(i, a, b); #endif cout<<"dfs"<<endl; dfs(root, 0); } return 0; }