二叉树的遍历
Posted jlyg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的遍历相关的知识,希望对你有一定的参考价值。
算法题目中有很多关于二叉树遍历的题目,以下就简要说一下可能的情况:
1、已知先序和中序,求后序。比如先序1 2 3 4 6 7 5,中序2 1 6 4 7 3 5。主要步骤有:1、求当前父节点,该节点是当前先序序列的第一个。2、在中序节点中找出该父节点的位置(i,从0开始计数)。3、获得左右孩纸节点,中序的序列左右孩纸(0到i-1),(i,len-1),先序左右孩纸就是(1,i)(i+1,len-1)。整理出:左孩纸先序节点(0,i-1),中序序列节点(1,i),右孩纸的先序(i,len-1),中序是(i+1,len-1)。4分别对左右孩纸进行1步骤。
#include<iostream> #include<cstdio> #include<set> #include<map> #include<vector> #include<iterator> #include<algorithm> #include<cstring> using namespace std; struct Node { int key; Node* left; Node* right; Node(){left=right=NULL;} }; void post_travel(Node* root) { if(root==NULL) { return; } post_travel(root->left); post_travel(root->right); printf("%d ",root->key); } Node* CreateTree(int* pre,int* inorder,int len) { if(len<=0) return NULL; Node* node = new Node(); node->key = *pre; if(len==1) { return node; } int i; for(i=0;i<len;++i) { if(inorder[i]==*pre) { break; } } node->left= CreateTree(pre+1,inorder,i); node->right = CreateTree(pre+i+1,inorder+i+1,len-i-1); return node; } int main() { freopen("test.txt","r",stdin); int n; scanf("%d",&n); int pre[n],inorder[n]; for(int i=0;i<n;++i) { scanf("%d",&pre[i]); } for(int i=0;i<n;++i) { scanf("%d",&inorder[i]); } Node* root = CreateTree(pre,inorder,n); post_travel(root); return 0; }
2、已知先序和后序,求中序(PAT原题1119)
难点在先序和后序构造的树不一定唯一,当然也有可能唯一解。所以我们要知道什么时候二叉树不唯一,什么时候唯一呢?那例题来说1 2 3 4 6 7 5和2 6 7 4 5 3 1,我们第一步可以得到当前父节点1。然后如何判断左右孩纸呢。
先序1后面那个就是下一个节点(2),后序1前面那个就是下一个节点(3),这时候你发现2和3不一样,说明什么呢--其实说明一个是左孩纸,一个是有孩纸。然后从先序中找右孩纸(3)的节点位置,然后我们可以找到左右孩纸的两颗树的序:左孩纸树的先序序列2,后序也是2,右孩纸的先序序列就是3 4 6 7 5,后序序列是6 7 4 5 3。然后不断重复以上步骤就好了。
再看另一个例子:1 2 3 4、2 4 3 1。为什么不唯一呢,找左右孩纸序列,左孩纸2 右孩纸3 4(先序),4 3(后序)。然后对右孩纸进行递归,你会发现根节点是3,孩纸节点只有一个(4),然后你就不知道他是属于左节点还是右节点了,所以不唯一。
所以结论:先序和后序求中序,要求必须是孩纸节点要么没有,要么是2个,不能有任意节点只有一个孩纸节点。
#include<iostream> #include<cstdio> #include<set> #include<map> #include<vector> #include<iterator> #include<algorithm> #include<cstring> using namespace std; struct Node { int key; Node* left; Node* right; Node() { left = right = NULL; } }; bool bOnly = true; Node* CreateTree(int* pre,int *post,int len) { Node *node = new Node(); node->key = *pre; if(len != 1) { //printf("len=%d ",len); if(*(pre+1) == *(post+len-2)) { bOnly = false; node->left = CreateTree(pre+1,post,len-1); } else { int rightkey = *(post+len-2); int rightindex = 0; for(;rightindex<len;++rightindex) { if(rightkey == *(pre+rightindex)) { break; } } node->left = CreateTree(pre+1,post,rightindex-1); node->right = CreateTree(pre+rightindex,post+rightindex-1,len-rightindex); } } return node; } bool bFirst = true; void inorder_travel(Node* root) { if(root == NULL) return; inorder_travel(root->left); if(bFirst) bFirst = false; else printf(" "); printf("%d",root->key); inorder_travel(root->right); } int main() { //freopen("test.txt","r",stdin); int n; scanf("%d",&n); int pre[n],post[n]; for(int i=0;i<n;++i) scanf("%d",&pre[i]); for(int i=0;i<n;++i) scanf("%d",&post[i]); Node* root = CreateTree(pre,post,n); if(bOnly) { printf("Yes "); } else { printf("No "); } inorder_travel(root); printf(" "); return 0; }
3、完全二叉树,已知中序排序求广度排序(PAT1064原题)
1064题是用二叉搜索树,所以先需要排序一下,然后构造树就行了
#include<iostream> #include<cstdio> #include<set> #include<map> #include<vector> #include<iterator> #include<algorithm> #include<cstring> using namespace std; struct Node { int key; Node* left; Node* right; Node(){left=right=NULL;} }; int n; int index2 = 0; Node* CreateTree(int* a,int k) { if(k>=n) return NULL; Node* node = new Node(); node->left = CreateTree(a,2*k+1); node->key = a[index2++]; node->right = CreateTree(a,2*k+2); return node; } bool bFirst = true; void level_travel(vector<Node*> vn) { if(vn.size()==0) return; vector<Node*> vnnext; for(int i=0;i<vn.size();++i) { if(bFirst) bFirst = false; else printf(" "); printf("%d",vn[i]->key); if(vn[i]->left) vnnext.push_back(vn[i]->left); if(vn[i]->right) vnnext.push_back(vn[i]->right); } level_travel(vnnext); } int main() { //freopen("test.txt","r",stdin); scanf("%d",&n); int inorder[n]; for(int i=0;i<n;++i) scanf("%d",&inorder[i]); sort(inorder,inorder+n); Node* root = CreateTree(inorder,0); vector<Node*> vn; vn.push_back(root); level_travel(vn); return 0; }
以上是关于二叉树的遍历的主要内容,如果未能解决你的问题,请参考以下文章