二叉树的基本操作
一、实验目的
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]);
}