二叉树的顺序存储—C++实现

二叉树的顺序存储—C++实现

二叉树的顺序存储依靠数组实现,最重要的是前序、中序、后序、层序四种遍历方式及获取深度、求所有结点、叶子结点的操作,总体不难,但递归是很重要的思想,要好好把握!

头文件如下:

#pragma once
#include<iostream>
#include<queue>
using namespace std;
#define Maxsize 100
class BinaryTree
{
public:
	BinaryTree();
	~BinaryTree();
	void CreatTree();//创建一棵二叉树
	void Getelem(int i);//获取树中第i个结点
	void PreOrderTraversel(int i = 1);//前序遍历,如果传入i的值就用传入的,没传入默认i为1
	void InOrderTraversel(int i = 1);//中序遍历
	void PostOrderTraversel(int i = 1);//后序遍历
	void LevelTraversel();//层序遍历
	int Depth(int i=1);//获取二叉树的深度
	int NodeNum(int i=1);//获取所有结点数目
	int LeafNum(int i=1);//获取所有叶子节点数目
private:
	int* ptr;//维护树中的每一个结点
	int length;//记录树中结点个数
};

具体实现如下:

#include<iostream>
#include<queue>
#include"二叉树的顺序存储.h"
#define MAXSIZE 100
using namespace std;
//二叉树的顺序存储其实还是用数组来实现
BinaryTree::BinaryTree()
{
	ptr=new int[MAXSIZE];//在堆区创建一块MAXSIZE这么大的内存,存放int类型数据,用ptr维护
	memset(ptr, 0, MAXSIZE);//对数组初始化:先用0来填充这些位置
}
BinaryTree::~BinaryTree()
{
	delete[] ptr;
}
void BinaryTree::CreatTree()//创建一棵二叉树
{
	int n;
	cout << "您想创建几个结点的二叉树:";
	cin >> n;
	if (n <= 0 || n > MAXSIZE)
	{
		cout << "您的输入有误,请重新输入!" << endl;
	}
	else
	{
		length = n;//**这里是最重要的,一定要先将树的长度指定好
		cout << "请分别输入各结点的值:";
		for (int i = 0; i < n; i++)
		{
			cin >> ptr[i];
		}
	}
}
void BinaryTree::Getelem(int i)//获取树中第i个结点
{
	if (ptr[i - 1] != 0)//树中的第i元素,下标为i-1,判断它是不是0
	{
		cout << ptr[i - 1] << " ";
	}
}
void BinaryTree::PreOrderTraversel(int i)//前序遍历
{
   //二叉树的前序遍历:根 左 右
	if (!length)
		return;//提高代码鲁棒性:判断二叉树是否为空,空返回false
	else
	{
		if (ptr[i-1]!=0)
		{
			Getelem(i);//先输出根节点的值
			PreOrderTraversel(2 * i);//递归左子树
			PreOrderTraversel(2 * i + 1);//递归右子树
		}
		else
			return;
	}
}
void BinaryTree::InOrderTraversel(int i)//中序遍历
{
	//二叉树的中序遍历:左 根 右
	if (!length)
		return;//提高代码鲁棒性:判断二叉树是否为空,空返回false
	else
	{
		if (ptr[i - 1] != 0)
		{
			InOrderTraversel(2 * i);//递归左子树
			Getelem(i);//先输出根节点的值
			InOrderTraversel(2 * i + 1);//递归右子树
		}
		else
			return;
	}
}
void BinaryTree::PostOrderTraversel(int i)//后序遍历
{
	//二叉树的后序遍历:左 右 根
	if (!length)
		return;//提高代码鲁棒性:判断二叉树是否为空,空返回false
	else
	{
		if (ptr[i - 1] != 0)
		{
			PostOrderTraversel(2 * i);//递归左子树
			PostOrderTraversel(2 * i + 1);//递归右子树
			Getelem(i);//先输出根节点的值
		}
		else
			return;
	}
}
void BinaryTree::LevelTraversel()//层序遍历
{
	//二叉树的层序遍历与上述三种遍历方式不同,要利用队列先进先出的特性来辅助实现
	if (!length)
		return ;
	else
	{
		queue<int>q;
		int i = 1;
		q.push(i);
		while (!q.empty())
		{
			if (ptr[q.front() - 1] != 0)
			{
				int i = q.front();
				q.push(i * 2);
				q.push(i * 2 + 1);
				Getelem(i);
				q.pop();
			}
			else return;
		}
	}
}
int BinaryTree::Depth(int i)//获取二叉树的深度
{
	//获取二叉树的深度先要判别左子树和右子树的深度哪个比较大,取大的再加root这一层就妥了
	if (!length)
		return 0;
	else
	{
		if (ptr[i - 1] != 0)//这里就是判断每一层的root是否存在
		{
			int m = Depth(i * 2);//递归左子树,获得左子树的深度
			int n = Depth(i * 2 + 1); //递归左子树,获得左子树的深度
			return m > n ? (m + 1) : (n + 1);//判断哪个深度大,取大的加一
		}
		else return 0;
	}
}
int BinaryTree::NodeNum(int i)//获取所有结点数目
{
	//左子树的所有节点加上右子树的所有节点加上root
	if (!length)
		return 0;
	else
	{
		if (ptr[i - 1] != 0)
		{
			return NodeNum(i * 2) + NodeNum(i * 2 + 1) + 1;
		}
		else
			return 0;
	}
}
int BinaryTree::LeafNum(int i)//获取所有叶子节点数目
{
	if (!length)
		return 0;
	else
	{
		if (ptr[i * 2] == 0 && ptr[2 * i + 1] == 0)
			return 1;//左右子树都不存在,就有个root
		else if (ptr[i * 2] != 0 && ptr[2 * i + 1] == 0)//左子树存在
			return LeafNum(i * 2);//递归左子树
		else if (ptr[i * 2] == 0 && ptr[2 * i + 1] != 0)//右子树存在
			return LeafNum(i * 2 + 1);//递归右子树
		else return LeafNum(i * 2) + LeafNum(i * 2 + 1);
		
	}
}
int main()
{
	BinaryTree bi;
	bi.CreatTree();
	cout << "先序递归遍历:"; 
	bi.PreOrderTraversel();
	cout << endl;
	cout << "中序递归遍历:"; 
	bi.InOrderTraversel();
	cout << endl;
	cout << "后序递归遍历:"; 
	bi.PostOrderTraversel();
	cout << endl;
	cout << "层次遍历:"; 
	bi.LevelTraversel();
	cout << endl;
	cout << "深度:" << bi.Depth();
	cout << endl;
	cout << "结点数:" << bi.NodeNum();
	cout << endl;
	cout << "叶子结点数:" << bi.LeafNum();
	cout << endl;
}

输出如下:

在这里插入图片描述
下一章会介绍二叉树的链式存储!!

  • 5
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值