《大话数据结构9》—— “二叉树的顺序存储结构”——C++、C# 代码实现

本文介绍了如何使用一维数组顺序存储完全二叉树,详细阐述了结点间的逻辑关系,包括双亲、左孩子和右孩子的编号推算。并提供了C++和C#的代码示例,但仅适用于完全二叉树和满二叉树。
摘要由CSDN通过智能技术生成

 

顺序存储结构:

二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的存储位置,也就是数组的下标要能体现结点之间的关秀,比如双亲与孩子的关系,左右结点的兄弟关系。

完全二叉树:

完全二叉树由于其结构上的特点,通常采用顺序存储方式存储。一棵有n个结点的完全二叉树的所有结点从1到n编号,就得到结点的一个线性系列。

如下图:完全二叉树除最下面一层外,各层都被结点充满了,每一层结点的个数恰好是上一层结点个数的2倍,因此通过一个结点的编号就可以推知它的双亲结点及左,右孩子结点的编号:

① 当 2i ≤ n 时,结点 i 的左孩子是 2i,否则结点i没有左孩子;

② 当 2i+1 ≤ n 时,结点i的右孩子是 2i+1,否则结点i没有右孩子;

③ 当 i ≠ 1 时,结点i的双亲是结点 i/2;

注意:由于数组下标从0开始,因此数组元素的下标等于结点在完全二叉树中的序号减1。

 

 一般二叉树:

对于一般的二叉树,如果仍按照从上至下,从左到右的顺序将树中的结点顺序存储在一维数组中,则数组元素下标之间的关系不能够反映二叉树中结点之间的逻辑关系。

这时假设将一般二叉树进行改造,增添一些并不存在的空结点,使之成为一棵完全二叉树的形式,然后再用一维数组顺序存储。在二叉树中假设增添的结点在数组中所对应的元素值为"空"用^表示。

下面是C++代码的示例:

#include<iostream>
#include<cassert>
using namespace std;

using ElementType = int;
using Status = void;
class FBTree
{
public:
	enum State
	{
		TT_ERROR = 0,
		TT_OK = 1
	};
public:
	FBTree(ElementType maxSize);
	Status treeClear();
	ElementType treeCreate(ElementType *array, int length);
	ElementType treeEmpty();
	Status treeDestory();
	ElementType treeDepth();
	Status treeLen();
	ElementType treeRoot( ElementType &rootData); //求树根的值
	ElementType treeValue(int index, ElementType &data);

	ElementType treeAssign(int index, ElementType value);

	ElementType treeParent(int index);

	ElementType treeLeftChild(int index);
	ElementType treeRightChild(int index);
	ElementType treeLeftSibling(int index);
	ElementType treeRightSibling(int index);
	ElementType treeInsertChild(int index, bool isLeft,int childDepth, int fatherDepth , FBTree insertTree);
	ElementType treeDeleteChild(int index, bool isLeft);
	Status preOrderTraverse();
	Status levelOrderTraverse();
	static int fatherData[];
	static int childData[];
private:
	ElementType *m_base;
	int m_size;//当前元素的最大容量
	int m_len;//当前的元素个数
	int m_maxIndex;//按照 完全二叉树的 排序方法, 所有节点 最大的 索引值,(相当于完全二叉树 的 节点数)
};
int FBTree::fatherData[] =
{
    1,//第一层
	2,3,//第二层
	4,5,6,7,
	8,0,0,0,0,0,0,0,
	16,0,0,0,0,

};
int FBTree::childData[]=
{
	1,
	2,3,
	0,0,0,0,
	0,0,0,
};
FBTree::FBTree(ElementType maxSize)
{
	assert(maxSize > 0);
	m_base = new ElementType[maxSize];
	assert(m_base != nullptr);
	m_len = 0;
	m_maxIndex = 0;
	m_size = maxSize;
	cout << "********************二叉树的顺序存储结构初始化成功!********************" << "\n" << endl;
}
Status FBTree::preOrderTraverse()
{
	
	for (int i = 0; i < m_size; i++)
	{
		cout << "第" << i + 1 << "层:";
		if (m_base[i] != 0)
		{
			cout << "\t" << m_base[i];
		}
		cout << endl;
	}
}
Status FBTree::levelOrderTraverse()
{
	int depth = treeDepth();
	for (int i = 0; i < depth; i++)
	{
		int depthNums =static_cast<int> (pow(2.0, i));//每一层节点数
		int startIndex =static_cast<int>(pow(2.0, i));
		cout << "第" << i + 1 << "层:";
		for (int j = 0; j < depthNums; j++)
		{
			int index = startIndex + j;
			if (index > m_maxIndex)
			{
				break;
			}
			cout << "\t"<< m_base[index - 1];
		}
		cout << endl;
	}
}

ElementType FBTree::treeDeleteChild(int index, bool isLeft)
{
	if (index < 1 || index > m_maxIndex || m_base[index - 1] == 0)//删除节点不存在
	{
		return TT_ERROR;
	}
	int childIndex = isLeft ? (2 * index): (2 * index + 1);
	//判断子树所在的层
	int depth = treeDepth();
	int childDepth = -1;
	for (int i = 1; i <= depth; i++)
	{
		if (childIndex < pow(2.0, i))
		{
			childDepth = i;
			break;
		}
	}
	//删除子树
	for (int i = 0; i <= depth - childDepth; i++)
	{
		int startIndex = static_cast <int>(childIndex * pow(2.0, i));//起始坐标
		for (int j = 0; j < pow(2.0, i); j++)
		{
			int deleteIndex = startIndex + j;
			int data = m_base[deleteIndex - 1];
			if (data != 0)
			{
				m_len--;
				m_base[deleteIndex - 1] = 0;
			}
		}
	}
	//重新寻找 maxIndex
	int oldSize = m_maxIndex;
	for (int i = 0; i < oldSize; i++)
	{
		int data = m_base[i];
		if (data != 0)
		{
			m_maxIndex = i + 1;
		}
	}
	return TT_OK;
}
ElementType FBTree::treeInsertChild(int index, bool isLeft, int childDepth, int fatherDepth, FBTree insertTree)
{//插入一个子树

	if (index >= 1 && index <= m_maxIndex && m_base[index - 1] !
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值