数据结构与算法实验-实验六:二叉树ADT的二叉链式实现

二叉树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
*/
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值