二叉树是数据结构中很重要的一部分,树的四种遍历:
前序,中序,后序,层次
涉及到了递归与队列的使用(当然也有非递归的遍历)
通过中序&前序或者中序&后序构建二叉树是一类很常见的考察方式
所以最好还是把所有的内容都实现一遍
写了三天的BUG今天终于能跑动了(ಥ _ ಥ)
本来的计划是按面向对象的方法实现节点类和树类,各种实现方式用成员函数表达,建树过程希望能用一个build函数的多态性完成,可惜大学C++没怎么好好学,最后草草的写了一个简易版的,其中很多部分的耦合性都太高了(终于发现软件工程的用场了)
写的不好,留了很多坑,以后慢慢加一点解释&代码完善
写完后不禁感慨专业课没有好好学
先上效果图:
代码:
#include <bits/stdc++.h>
#define Max 1024
#define ElemType int
using namespace std;
ElemType pre[Max],in[Max],post[Max],n;
int num,cnt = 0;
typedef struct node
{
ElemType data;
struct node *left,*right;
};
node* root;
node* newNode(ElemType e)
{
node* u = new(node);
u->left = u->right = NULL;
u->data = e;
return u;
}
node* pre_in_build(ElemType *pre,ElemType *in,int n)
{
int idx;
for(idx=0; idx<n; idx++)
if(pre[0]==in[idx])
break;
node* u = newNode(in[idx]);
if(idx>0)
u->left = pre_in_build(pre+1,in,idx);
if(idx<n-1)
u->right = pre_in_build(pre+idx+1,in+idx+1,n-idx-1);
return u;
}
node* in_post_build(ElemType *post,ElemType *in,int n)
{
node* u;
for(int i=0; i<n; i++)
{
if(post[num-1]==in[i])
{
u = newNode(in[i]);
u->left = in_post_build(post-n+i,in,i);
u->right = in_post_build(post-1,in+i+1,n-i-1);
return u;
}
}
return NULL;
}
void deleteNode(node* u)
{
if(u==NULL)
return;
deleteNode(u->left);
deleteNode(u->right);
delete u;
}
void preOrder(node* u)
{
if(u==NULL)
return;
if(u==root)
cout<<u->data<<' ';
else
cout<<u->data<<' ';
preOrder(u->left);
preOrder(u->right);
}
void inOrder(node* u)
{
if(u==NULL)
return;
inOrder(u->left);
if(u==root)
cout<<u->data<<' ';
else
cout<<u->data<<' ';
inOrder(u->right);
}
void postOrder(node* u)
{
if(u==NULL)
return;
postOrder(u->left);
postOrder(u->right);
if(u==root)
cout<<u->data;
else
cout<<u->data<<' ';
}
void levelOrder(node *u)
{
cnt = 0;
queue<node*> q;
while(!q.empty())
q.pop();
q.push(u);
node *tmp;
while(!q.empty())
{
tmp = q.front();
q.pop();
if(cnt==num-1)
cout<<tmp->data<<endl;
else
cout<<tmp->data<<' ',cnt++;
if(tmp->left!=NULL)
q.push(tmp->left);
if(tmp->right!=NULL)
q.push(tmp->right);
}
}
int main()
{
int choice,n;
cout<<"------------------------------"<<endl;
cout<<"choose your construct option: "<<endl;
cout<<"1.pre&in Order->post&level "<<endl;
cout<<"2.in&post Order->pre&level "<<endl;
cout<<"------------------------------"<<endl;
while(1)
{
cin>>choice;
switch(choice)
{
case 1:
deleteNode(root);
cout<<"Input number of nodes: "<<endl;
cout<<"1st line:pre, 2nd line in "<<endl;
cin>>n;
num = n;
for(int i=0; i<n; i++)
cin>>pre[i];
for(int i=0; i<n; i++)
cin>>in[i];
root = pre_in_build(pre,in,n);
break;
case 2:
deleteNode(root);
cout<<"Input number of nodes: "<<endl;
cout<<"1st line:psot, 2nd line in"<<endl;
cin>>n;
num = n;
for(int i=0; i<n; i++)
cin>>post[i];
for(int i=0; i<n; i++)
cin>>in[i];
root = in_post_build(post,in,n);
break;
default:
cout<<"invalid input!"<<endl;
exit(0);
break;
}
cout<<"preOrder:"<<endl;
preOrder(root);
cout<<endl;
cout<<"inOrder:"<<endl;
inOrder(root);
cout<<endl;
cout<<"postOrder:"<<endl;
postOrder(root);
cout<<endl;
cout<<"levelOrder"<<endl;
levelOrder(root);
cout<<endl;
}
return 0;
}
HDU 1710 Binary Tree Traversals
传送门
根据先序中序遍历写出后序遍历
A binary tree is a finite set of vertices that is either empty or consists of a root r and two disjoint binary trees called the left and right subtrees. There are three most important ways in which the vertices of a binary tree can be systematically traversed or ordered. They are preorder, inorder and postorder. Let T be a binary tree with root r and subtrees T1,T2.
In a preorder traversal of the vertices of T, we visit the root r followed by visiting the vertices of T1 in preorder, then the vertices of T2 in preorder.
In an inorder traversal of the vertices of T, we visit the vertices of T1 in inorder, then the root r, followed by the vertices of T2 in inorder.
In a postorder traversal of the vertices of T, we visit the vertices of T1 in postorder, then the vertices of T2 in postorder and finally we visit r.
Now you are given the preorder sequence and inorder sequence of a certain binary tree. Try to find out its postorder sequence.
Input
The input contains several test cases. The first line of each test case contains a single integer n (1<=n<=1000), the number of vertices of the binary tree. Followed by two lines, respectively indicating the preorder sequence and inorder sequence. You can assume they are always correspond to a exclusive binary tree.
Output
For each test case print a single line specifying the corresponding postorder sequence.
#include <bits/stdc++.h>
#define Max 1024
#define ElemType int
using namespace std;
ElemType pre[Max],in[Max],n;
typedef struct node
{
ElemType data;
struct node *left,*right;
};
node* root;
node* newNode(ElemType e)
{
node* u = new(node);
u->left = u->right = NULL;
u->data = e;
return u;
}
node* build(ElemType *pre,ElemType *in,int n)
{
int idx;
for(idx=0; idx<n; idx++)
if(pre[0]==in[idx])
break;
node* u = newNode(in[idx]);
if(idx>0)
u->left = build(pre+1,in,idx);
if(idx<n-1)
u->right = build(pre+idx+1,in+idx+1,n-idx-1);
return u;
}
void deleteNode(node* u)
{
if(u==NULL)
return;
deleteNode(u->left);
deleteNode(u->right);
delete u;
}
void postOrder(node* u)
{
if(u==NULL)
return;
postOrder(u->left);
postOrder(u->right);
if(u==root)
cout<<u->data;
else
cout<<u->data<<' ';
}
int main()
{
int n;
while(cin>>n)
{
for(int i=0; i<n; i++)
cin>>pre[i];
for(int i=0; i<n; i++)
cin>>in[i];
deleteNode(root);
root = build(pre,in,n);
postOrder(root);
cout<<endl;
}
return 0;
}
PAT 1020 Tree Traversals
根据后序中序遍历求层次遍历
个人感觉这个更难,无论是建树过程还是求层次遍历
传送门
Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (<=30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.
Sample Input:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
Sample Output:
4 1 6 3 5 7 2
代码:
#include <bits/stdc++.h>
#define Max 1024
#define ElemType int
using namespace std;
ElemType pre[Max],in[Max],post[Max],n;
int num,cnt = 0;
typedef struct node
{
ElemType data;
struct node *left,*right;
};
node* root;
node* newNode(ElemType e)
{
node* u = new(node);
u->left = u->right = NULL;
u->data = e;
return u;
}
node* build(ElemType *post,ElemType *in,int n)
{
node* u;
for(int i=0; i<n; i++)
{
if(post[num-1]==in[i])
{
u = newNode(in[i]);
u->left = build(post-n+i,in,i);
u->right = build(post-1,in+i+1,n-i-1);
return u;
}
}
return NULL;
}
void deleteNode(node* u)
{
if(u==NULL)
return;
deleteNode(u->left);
deleteNode(u->right);
delete u;
}
void levelOrder(node *u)
{
cnt = 0;
queue<node*> q;
while(!q.empty())
q.pop();
q.push(u);
node *tmp;
while(!q.empty())
{
tmp = q.front();
q.pop();
if(cnt==num-1)
cout<<tmp->data<<endl;
else
cout<<tmp->data<<' ',cnt++;
if(tmp->left!=NULL)
q.push(tmp->left);
if(tmp->right!=NULL)
q.push(tmp->right);
}
}
int main()
{
int n;
while(cin>>n)
{
num = n;
for(int i=0; i<n; i++)
cin>>post[i];
for(int i=0; i<n; i++)
cin>>in[i];
deleteNode(root);
root = build(post,in,n);
levelOrder(root);
}
return 0;
}
UVa 536 Tree Recovery
把ElemaType改成char型,调成一下I/O格式就能AC了
传送门
Little Valentine liked playing with binary trees very much. Her favorite game was constructing randomly
looking binary trees with capital letters in the nodes.
This is an example of one of her creations:
D
/
/
B E
/ \
/ \
A C G
/
/
F
To record her trees for future generations, she wrote down two strings for each tree: a preorder
traversal (root, left subtree, right subtree) and an inorder traversal (left subtree, root, right subtree).
For the tree drawn above the preorder traversal is DBACEGF and the inorder traversal is ABCDEFG.
She thought that such a pair of strings would give enough information to reconstruct the tree later
(but she never tried it).
Now, years later, looking again at the strings, she realized that reconstructing the trees was indeed
possible, but only because she never had used the same letter twice in the same tree.
However, doing the reconstruction by hand, soon turned out to be tedious.
So now she asks you to write a program that does the job for her!
Input
The input file will contain one or more test cases.
Each test case consists of one line containing two strings ‘preord’ and ‘inord’, representing the
preorder traversal and inorder traversal of a binary tree. Both strings consist of unique capital letters.
(Thus they are not longer than 26 characters.)
Input is terminated by end of file.
Output
For each test case, recover Valentine’s binary tree and print one line containing the tree’s postorder
traversal (left subtree, right subtree, root).
#include <bits/stdc++.h>
#define Max 1024
#define ElemType char
using namespace std;
ElemType pre[Max],in[Max],post[Max],n;
int num,cnt = 0;
typedef struct node
{
ElemType data;
struct node *left,*right;
};
node* root;
node* newNode(ElemType e)
{
node* u = new(node);
u->left = u->right = NULL;
u->data = e;
return u;
}
node* pre_in_build(ElemType *pre,ElemType *in,int n)
{
int idx;
for(idx=0; idx<n; idx++)
if(pre[0]==in[idx])
break;
node* u = newNode(in[idx]);
if(idx>0)
u->left = pre_in_build(pre+1,in,idx);
if(idx<n-1)
u->right = pre_in_build(pre+idx+1,in+idx+1,n-idx-1);
return u;
}
void deleteNode(node* u)
{
if(u==NULL)
return;
deleteNode(u->left);
deleteNode(u->right);
delete u;
}
void postOrder(node* u)
{
if(u==NULL)
return;
postOrder(u->left);
postOrder(u->right);
cout<<u->data;
}
int main()
{
while(~scanf("%s%s",pre,in))
{
n = strlen(pre);
deleteNode(root);
root = pre_in_build(pre,in,n);
postOrder(root);
cout<<endl;
}
return 0;
}