二叉树ADT的二叉链式实现
假设二叉数的数据元素为字符,采用二叉链式存储结构。请编码实现二叉树ADT,其中包括创建二叉树、遍历二叉树(深度、广度)、求二叉树的深度(高度)、计算二叉树的元素个数、计算二叉树的叶子数、二叉树的格式输出等。根据输入的符号,执行相应的操作。如下:C:创建二叉树,创建成功输出 “Created success!”。要求实现两种创建算法。输入数字“1" ,是根据完全前序序列创建二叉树,#表示空结点(空子树);下一行输入二叉树的完全前序序列。 输入数字“2”,是根据二叉树的前序和中序序列创建二叉树,后面有三行,分别输入元素个数、前序序列和中序序列。H:求二叉树的高度; 输出: Height=高度
L:计算二叉树的叶子数;输出:Leaves=叶子个数N:计算二叉树中元素总个数;输出:Nodes=结点个数1:先序遍历二叉树;输出:Preorder is:序列 .2:中序遍历二叉树;输出:Inorder is:序列 .3:后序遍历二叉树;输出:Postorder is:序列 .4:广度遍历二叉树;输出:BFSorder is:序列 .F:查找值为x的结点个数;输出:The count of x is 个数 .
P:以目录缩格文本形式输出所有节点。输出:The tree is:(换行,下面各行是输出的二叉树)X:退出
例如:
样例输入1:
C
1
ABC##DE#G##F###
H
L
N
1
2
3
4
F
A
P
X
样例输出1:
Created success!
Height=5
Leaves=3
Nodes=7
Preorder is:A B C D E G F .
Inorder is:C B E G D F A .
Postorder is:C G E F D B A .
BFSorder is:A B C D E F G .
The count of A is 1
The tree is:
A
B
C
D
E
G
F
样例输入2:
C
2
6
abcdef
abcdef
H
L
N
1
2
3
4
F
h
P
X
样例输出2:
Created success!
Height=6
Leaves=1
Nodes=6
Preorder is:a b c d e f .
Inorder is:a b c d e f .
Postorder is:f e d c b a .
BFSorder is:a b c d e f .
The count of h is 0
The tree is:
a
b
c
d
e
f
这个题唯一的bug点在于可能二叉树建的有问题,另提供一组数据如下:
输入:
C
2
6
GDAFEMHZ
ADEFGHMZ
H
L
N
1
2
3
4
F
A
P
X
输出:
Created success!
Height=4
Leaves=4
Nodes=8
Preorder is:G D A F E M H Z .
Inorder is:A D E F G H M Z .
Postorder is:A E F D H Z M G .
BFSorder is:G D M A F H Z E .
The count of A is 1
The tree is:
G
D
A
F
E
M
H
Z
至于难点,我认为在于建树。二叉树框架建立如下:
struct node
{
char data;
struct node *left,*right;
};
struct node *p,*t,*head=NULL,*q;
对于完全前序序列,暴力跑(中,左,右),注意申请空间和“#”的情况:
int pos1=0;
void create1(string str1,int n,struct node* &head1)
{
p=(struct node*)malloc(sizeof(struct node));
p->data=str1[pos1];
p->left=NULL;
p->right=NULL;
head1=p;
if(head1->data!='#')
{
pos1++;
create1(str1,n,head1->left);
pos1++;
create1(str1,n,head1->right);
}
}
对于前序和中序,我的做法是将其转换为完全前序:
假设前序为:ABCDEGF
假设中序为:CBEGDFA
我们可以发现,前序的排列为“中,左,右”;中序的排列为“左,中,右”,即,我们只需找到中序“中”的位置,便可将其分为以“中”为父结点的左子树和右子树。
以此为思路,我们从前往后遍历其“前序序列”,对于每一个元素,在中序序列中找出与之对应的元素,并将串分为左右两部分(在遇到之前的结点时应立即停止,这里应递归处理,下面会提到),若是左空,则在其后立即加上#,若是右空,则在其处理完左串之后加上#,若是左右皆空,则立即加上##,若是左右皆非空,则继续遍历。重复此过程直至串尾即可得完全前序序列。
图示如下:
(前两步都能看懂,就不解释了)
第三步注意,扫描到B时应立即停止(即上面所说的“遇到之前的结点时应立即停止”)
后面几步按照这个规律,应该也是可以看懂的了。
转换的函数如下:
string zhuan(string str1,int n,int pos,string str2,int m)
{
if(pos==0)
memset(flag1,0,sizeof(flag1));
char ch=str1[pos];
string ss1="";
string ss2="";
int vv=0;
rep(i,0,m-1)
{
if(str2[i]==ch)
{
vv=i;
flag1[i]=1;
break;
}
}
per(i,0,vv-1)
{
if(flag1[i]==0)
{
ss1+=str2[i];
}
else
break;
}
reverse(ss1.begin(),ss1.end());
rep(i,vv+1,m-1)
{
if(flag1[i]==0)
{
ss2+=str2[i];
}
else
break;
}
string u="";
u+=ch;
if(ss1==""&&ss2=="")
return u+="##";
eif(ss1=="")
return u+"#"+zhuan(str1,n,pos+1,str2,m);
eif(ss2=="")
return u+zhuan(str1,n,pos+1,str2,m)+"#";
else
{
string uu=u+zhuan(str1,n,pos+1,str2,m);
return uu+zhuan(str1,n,pos+ss1.size()+1,str2,m);
}
}
寻找叶子结点个数和层数,都是遍历一遍便可以知道的了,这里不再赘述,函数如下:
void gen(struct node *t1,int u)
{
if(t1==NULL)
return;
len=max(len,u);
gen(t1->left,u+1);
gen(t1->right,u+1);
}
void gen1(struct node *t1,int u)
{
if(t1==NULL)
return;
if(t1->data!='#')
{
que[u].push(t1->data);
if(t1->left->data=='#'&&t1->right->data=='#')
zi++;
}
gen1(t1->left,u+1);
gen1(t1->right,u+1);
}
最后以目录缩格文本形式打出所有结点:
void bianli(struct node *t1,int u)
{
if(t1==NULL)
return;
if(t1->data!='#')
{
if(u==0)
cout<<t1->data<<endl;
else
{
rep(i,1,u)
cout<<" ";
cout<<t1->data<<endl;
}
}
bianli(t1->left,u+1);
bianli(t1->right,u+1);
}
前序遍历,我采取直接消掉“#”的方式即可得到(因为我们知道完全前序序列):
eif(ch=='1')
{
cout<<"Preorder is:";
rep(i,0,num1-1)
{
cout<<qian[i]<<" ";
}
cout<<"."<<endl;
}
中序和后序遍历使用递归:
void zhong(struct node *t1,int u)
{
if(t1==NULL)
return;
if(t1->data=='#')
return;
zhong(t1->left,u+1);
cout<<t1->data<<" ";
zhong(t1->right,u+1);
}
void hou(struct node *t1,int u)
{
if(t1==NULL)
return;
if(t1->data=='#')
return;
hou(t1->left,u+1);
hou(t1->right,u+1);
cout<<t1->data<<" ";
}
广度遍历,结合上边的gen1函数,将每一层的结点打入一个队列中,最后即遍历每一层,依次打出队列中所存点即可。
eif(ch=='4')
{
cout<<"BFSorder is:";
rep(i,0,len-1)
{
while(!que[i].empty())
{
cout<<que[i].front()<<" ";
que[i].pop();
}
}
cout<<"."<<endl;
}
完整代码如下:
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef pair<int,int> pii;
typedef queue<int> q_i;
typedef queue<string> q_s;
typedef queue<double> q_d;
typedef queue<ll> q_ll;
typedef queue<char> q_c;
typedef priority_queue<int> pq_i;
typedef priority_queue<string> pq_s;
typedef priority_queue<double> pq_d;
typedef priority_queue<ll> pq_ll;
typedef stack<int> s_i;
typedef stack<string> s_s;
typedef stack<double> s_d;
typedef stack<ll> s_ll;
typedef stack<char> s_c;
typedef map<ll,ll> m_ll_ll;
typedef map<int,ll> m_i_ll;
typedef map<int,int> m_i_i;
typedef map<string,ll> m_s_ll;
typedef map<char,int> m_c_i;
typedef map<char,ll> m_c_ll;
const ll INF=0x3f3f3f3f;
#define rep(i,l,r) for(ll i=l;i<=r;i++)
#define per(i,l,r) for(ll i=r;i>=l;i--)
#define eif else if
#define N 2000005
#define mm(dp) memset(dp,0,sizeof(dp))
#define mm1(dp) memset(dp,-1,sizeof(dp))
#define mm2(dp) memset(dp,0x3f,sizeof(dp))
#define IT set<int>::iterator
#define fs(n) fixed<< setprecision(n)
const double e=2.71828182845;
const double pi = acos(-1.0);
int len=0;
int zi=0;
queue<char>que[2005];
class Tree
{
public:
struct node
{
char data;
struct node *left,*right;
};
struct node *p,*t,*head=NULL,*q;
int flag1[200005];
int pos1=0;
void create1(string str1,int n,struct node* &head1)
{
p=(struct node*)malloc(sizeof(struct node));
p->data=str1[pos1];
p->left=NULL;
p->right=NULL;
head1=p;
if(head1->data!='#')
{
pos1++;
create1(str1,n,head1->left);
pos1++;
create1(str1,n,head1->right);
}
}
void gen(struct node *t1,int u)
{
if(t1==NULL)
return;
len=max(len,u);
gen(t1->left,u+1);
gen(t1->right,u+1);
}
void gen1(struct node *t1,int u)
{
if(t1==NULL)
return;
if(t1->data!='#')
{
que[u].push(t1->data);
if(t1->left->data=='#'&&t1->right->data=='#')
zi++;
}
gen1(t1->left,u+1);
gen1(t1->right,u+1);
}
void bianli(struct node *t1,int u)
{
if(t1==NULL)
return;
if(t1->data!='#')
{
if(u==0)
cout<<t1->data<<endl;
else
{
rep(i,1,u)
cout<<" ";
cout<<t1->data<<endl;
}
}
bianli(t1->left,u+1);
bianli(t1->right,u+1);
}
void zhong(struct node *t1,int u)
{
if(t1==NULL)
return;
if(t1->data=='#')
return;
zhong(t1->left,u+1);
cout<<t1->data<<" ";
zhong(t1->right,u+1);
}
void hou(struct node *t1,int u)
{
if(t1==NULL)
return;
if(t1->data=='#')
return;
hou(t1->left,u+1);
hou(t1->right,u+1);
cout<<t1->data<<" ";
}
string zhuan(string str1,int n,int pos,string str2,int m)
{
if(pos==0)
memset(flag1,0,sizeof(flag1));
char ch=str1[pos];
string ss1="";
string ss2="";
int vv=0;
rep(i,0,m-1)
{
if(str2[i]==ch)
{
vv=i;
flag1[i]=1;
break;
}
}
per(i,0,vv-1)
{
if(flag1[i]==0)
{
ss1+=str2[i];
}
else
break;
}
reverse(ss1.begin(),ss1.end());
rep(i,vv+1,m-1)
{
if(flag1[i]==0)
{
ss2+=str2[i];
}
else
break;
}
string u="";
u+=ch;
if(ss1==""&&ss2=="")
return u+="##";
eif(ss1=="")
return u+"#"+zhuan(str1,n,pos+1,str2,m);
eif(ss2=="")
return u+zhuan(str1,n,pos+1,str2,m)+"#";
else
{
string uu=u+zhuan(str1,n,pos+1,str2,m);
return uu+zhuan(str1,n,pos+ss1.size()+1,str2,m);
}
}
};
map<char,int>mapp;
string qian="";
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
Tree tree;
int num1=0;
while(1)
{
char ch;
cin>>ch;
if(ch=='X')
break;
eif(ch=='C')
{
num1=0;
qian="";
int nm;
cin>>nm;
if(nm==1)
{
string str;
cin>>str;
rep(i,0,str.size()-1)
{
if(str[i]!='#')
{
num1++;
mapp[str[i]]++;
qian.push_back(str[i]);
}
}
int num=str.size();
tree.create1(str,num,tree.head);
//cout<<qian<<"ll"<<endl;
cout<<"Created success!"<<endl;
}
else
{
int n;
cin>>n;
string s1,s2;
cin>>s1;
cin>>s2;
string s=tree.zhuan(s1,s1.size(),0,s2,s2.size());
//cout<<s<<endl;
int num=s.size();
tree.create1(s,num,tree.head);
rep(i,0,s.size()-1)
{
if(s[i]!='#')
{
num1++;
mapp[s[i]]++;
qian.push_back(s[i]);
}
}
//cout<<qian<<"ll"<<endl;
cout<<"Created success!"<<endl;
}
tree.gen(tree.head,0);
tree.gen1(tree.head,0);
}
eif(ch=='P')
{
cout<<"The tree is:"<<endl;
tree.bianli(tree.head,0);
}
eif(ch=='H')
{
cout<<"Height="<<len<<endl;
}
eif(ch=='L')
{
cout<<"Leaves="<<zi<<endl;
}
eif(ch=='N')
{
cout<<"Nodes="<<num1<<endl;
}
eif(ch=='1')
{
cout<<"Preorder is:";
rep(i,0,num1-1)
{
cout<<qian[i]<<" ";
}
cout<<"."<<endl;
}
eif(ch=='2')
{
cout<<"Inorder is:";
tree.zhong(tree.head,0);
cout<<"."<<endl;
}
eif(ch=='3')
{
cout<<"Postorder is:";
tree.hou(tree.head,0);
cout<<"."<<endl;
}
eif(ch=='4')
{
cout<<"BFSorder is:";
rep(i,0,len-1)
{
while(!que[i].empty())
{
cout<<que[i].front()<<" ";
que[i].pop();
}
}
cout<<"."<<endl;
}
eif(ch=='F')
{
char t;
cin>>t;
cout<<"The count of "<<t<<" is "<<mapp[t]<<endl;
}
}
return 0;
}
/*
5
ABCDE
ADCEB
*/
/*
C
2
7
ABCDEGF
CBEGDFA
*/
/*
C
2
6
GDAFEMHZ
ADEFGHMZ
H
L
N
1
2
3
4
F
A
P
X
*/