中南大学数据结构实验三

二叉树的基本操作

一、实验目的
1、掌握用指针类型描述、访问和处理二叉树的运算;
2、掌握二叉树的结构特征,以及各种存储结构的特点及适用范围;
3、熟练掌握递归程序设计方法、以及栈的应用
二、实验内容
以二叉链表作存储结构,编写程序,实现如下的功能:
1、根据输入的数据建立一个二叉树;
2、分别采用前序、中序、后序的遍历方式显示输出二叉树的遍历结果
3、采用非递归的编程方法,分别统计二叉树的节点个数、度为1、度为2和叶子节点的个数,以及数据值的最大值和最小值。
4、(选作内容)试编写按层次顺序遍历二叉树的算法。参考算法思想:要采用一个队列q,先将二叉树根结点入队列,然后退队列,输出该结点;若它有左子树,便将左子树根结点入队列;若它有右子树,便将右子树根结点入队列,直到队列空为止。因为队列的特点是先进先出,从而达到按层次顺序遍历二叉树的目的。
三、 实验要求
1.认真阅读和掌握本实验的算法。
2.上机将本算法实现。
3.在程序的编写中尽量与专业的编程规范靠拢,系统代码采用结构化的编程方式,力求设计代码以及注释等规范,
4.保存和打印出程序的运行结果,并结合程序进行分析。
四、实验代码

// 输入格式
// 第一行包含一个整数n,表示节点数目
// 第二行包含n个整数,表示n个节点
// 输入格式如下
// 6
// 1 2 3 4 5 6
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
struct Node{
    int val;
    Node* left;
    Node* right;
};
Node nodes[100];
//前序遍历
void PreOrder(Node* root)
{
    if(root==NULL)
        return ;
    cout<<root->val<<" ";
    PreOrder(root->left);
    PreOrder(root->right);
}
//中序遍历
void MidOrder(Node* root)
{
    if(root==NULL)
        return ;
    MidOrder(root->left);
    cout<<root->val<<" ";
    MidOrder(root->right);
}
//后序遍历
void LatterOrder(Node* root)
{
    if(root==NULL)
        return ;
    LatterOrder(root->left);
    LatterOrder(root->right);
    cout<<root->val<<" ";
}
void CountNumbersOfNode(Node* root)
{
    if(root==NULL)
        return ;
    int allcnt=0;//所有的节点
    int cnt1=0;//节点度为1的数量
    int cnt2=0;//节点度为2的数量
    int cnt0=0;//叶子节点的数量
    int mx=0;//将最大值初始化为一个较小的数
    int mn=1e9;//将最小值初始化为一个较大的数
    //前面前中后序遍历都是采取递归实现的,此处采取非递归前序遍历统计各种节点数量,需要用到栈(可以利用c++自带的栈或者手写一个栈)
    //这里采用自带的栈
    stack<Node*> mystack;
    while(root!=NULL||!mystack.empty())//节点不为空或者栈中还有节点,这里理解不了可以用简单的数据画图帮助理解
    {
        while(root!=NULL)//当前节点不为空
        {
            allcnt++;
            mx=max(mx,root->val);
            mn=min(mn,root->val);
            if(root->left!=NULL||root->right!=NULL)
            {
                if(root->left!=NULL&&root->right!=NULL)
                    cnt2++;//当前节点为度为2的节点
                else
                    cnt1++;//否则当前节点为度为1的节点
            } else
                cnt0++;//左右孩子都为空则当前节点为叶子节点
            mystack.push(root);
            root=root->left;
        }
        Node* temp=mystack.top();
        mystack.pop();
        root=temp->right;
    }
    cout<<"结点个数为:"<<allcnt<<endl;
    cout<<"度为1的结点个数为:"<<cnt1<<endl;
    cout<<"度为2的结点个数为:"<<cnt2<<endl;
    cout<<"叶子结点个数为:"<<cnt0<<endl;
    cout<<"最大值为:"<<mx<<endl;
    cout<<"最小值为:"<<mn<<endl;
}
void LevelOrder(Node* root)
{
    if(root==NULL)
        return ;
    //利用队列
    queue<Node*> q;
    q.push(root);
    while(q.size()>0)//队列不为空
    {
        int size=q.size();//每一层的节点数目
        while(size>0)
        {
            Node* temp=q.front();
            q.pop();//将当前节点出队列
            //打印数据
            cout<<temp->val<<" ";
            if(temp->left!=NULL)//左孩子不为空则入队列
                q.push(temp->left);
            if(temp->right!=NULL)
                q.push(temp->right);
            size--;//每遍历一个节点,size减1
        }
        cout<<endl;
    }
}
int main()
{
    int n;//假设输入n个数据
    cin>>n;
    for(int i=1;i<=n;i++)//这里的节点下标从1开始便于后续计算
    {
        int t;
        cin>>t;
        nodes[i]={t,NULL,NULL};//创建节点
    }
    //将节点连接起来创建二叉树
    for(int i=1;i<n;i++)
    {
        int l=2*i;//左孩子的下标为当前父节点的2倍
        int r=2*i+1;//右孩子的下标为当前父节点的2倍+1
        if(l<=n)
            nodes[i].left=&nodes[l];//left为node类型的指针数据,所以需要取地址
        if(r<=n)
            nodes[i].right=&nodes[r];
    }
    cout<<"前序遍历: ";
    PreOrder(&nodes[1]);
    cout<<endl;
    cout<<"中序遍历: ";
    MidOrder(&nodes[1]);
    cout<<endl;
    cout<<"后序遍历: ";
    LatterOrder(&nodes[1]);
    cout<<endl;
    CountNumbersOfNode(&nodes[1]);
    cout<<"层序遍历结果为: "<<endl;
    LevelOrder(&nodes[1]);
}

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值