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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34536551/article/details/84201301

顺序存储结构:

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

完全二叉树:

完全二叉树由于其结构上的特点,通常采用顺序存储方式存储。一棵有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] != 0)//父 节点 必须已存在
	{
		int totalDepth = childDepth + fatherDepth;//加入子树后的深度
		int needSize = static_cast <int>(pow(2.0, totalDepth) - 1);//总共需要的 节点数
		
		int childRootIndex = isLeft ? (2 * index) : (2 * index + 1);//子树 根节点 在 父树的 索引
		if (m_base[childRootIndex - 1] == 0)//子树不存在,插入子树..
		{
			for (int i = 0; i < childDepth; i++)//遍历子树的每一层
			{
				int childStartIndex = static_cast <int> (pow(2.0, i));//子树每一层起始坐标
				int fatherStartIndex = static_cast <int> (childRootIndex * pow(2.0, i)); //父亲每一层的起始坐标
				int total = static_cast <int>(pow(2.0, i));
				for (int j = 0; j < total; j++)//每一层几个..
				{
					int childIndex = childStartIndex + j;
					if (childIndex > insertTree.m_maxIndex)
					{
						break;
					}
					int fatherIndex = fatherStartIndex + j;
					int childData = insertTree.m_base[childIndex - 1];
					m_base[fatherIndex - 1] = childData;
					if (childData != 0)
					{
						m_len++;
						m_maxIndex = m_maxIndex > fatherIndex ? m_maxIndex : fatherIndex;
					}

				}
			}
		}
		else//孩子节点已存在
		{
			return TT_ERROR;
		}
	}
	else//父节点不存在
	{
		return TT_ERROR;
	}
	return TT_OK;

}
ElementType FBTree::treeRightSibling(int index)
{//若该结点,有右兄弟,返回该结点的右兄弟
	
	int rightIndex = index + 1;
	if (index <= 1 || rightIndex > m_maxIndex || (index % 2 != 0))
	{
		return TT_ERROR;
	}
	ElementType data = m_base[index - 1];
	if (data != 0 && m_base[rightIndex - 1] != 0)// 左右节点都存在
	{
		return m_base[rightIndex - 1];
	}
	return TT_ERROR;
}


ElementType FBTree::treeLeftSibling(int index)
{//若该结点,有左兄弟,返回该结点的左兄弟

	int leftIndex = index - 1;
	//根节点 和 第二个节点 都没有左兄弟,并且 左兄弟的节点 树 是 2的 倍数
	if (index <= 2 || index > m_maxIndex || (leftIndex % 2 != 0))
	{
		return TT_ERROR;
	}
	ElementType data = m_base[index - 1];
	if (data != 0 && (m_base[leftIndex - 1] != 0))// 左右节点都存在
	{
		return m_base[leftIndex - 1];
	}
	return TT_ERROR;
}
ElementType FBTree::treeRightChild(int index)
{//返回该结点的最右孩子,叶子结点除外
	int rChildIndex = 2 * index + 1;
	if (index < 1 || index > m_maxIndex || rChildIndex > m_maxIndex)
	{
		return TT_ERROR;
	}
	ElementType data = m_base[index - 1];
	if (data != 0 && (m_base[rChildIndex - 1] != 0))// 节点存在,并且孩子节点存在
	{
		return m_base[rChildIndex - 1];
	}
	return TT_ERROR;
}
ElementType FBTree::treeLeftChild(int index)
{//返回该结点的最左孩子,叶子结点除外
	int lChildIndex = 2 * index;
	if (index < 1 || index > m_maxIndex || lChildIndex > m_maxIndex)
	{
		return TT_ERROR;
	}
	ElementType data = m_base[index - 1];
	if (data != 0 && (m_base[lChildIndex - 1] != 0))// 节点存在,并且孩子节点存在
	{
		return m_base[lChildIndex - 1];
	}
	return TT_ERROR;

}
ElementType FBTree::treeParent(int index)
{//返回除树根之外的某结点的双亲
	if (index <= 1 || index > m_maxIndex)//节点超越范围或者 节点 为根节点
	{
		return TT_ERROR;
	}
	ElementType data = m_base[index - 1];// 只要双亲结点存在
	if (data != 0)//节点存在
	{
		return (m_base[index / 2 - 1]);
	}
	return TT_ERROR;
}
ElementType FBTree::treeAssign(int index, ElementType value)
{//给树中的某一结点赋值为value

	if (index < 1 || index > m_maxIndex)
	{
		return TT_ERROR;
	}
	ElementType oldValue = m_base[index - 1]; //只要该结点存在
	if (oldValue != 0)
	{
		m_base[index - 1] = value;
		return TT_OK;
	}
	//子树不存在,赋值失败
	return TT_ERROR;
}
ElementType FBTree::treeValue(int index, ElementType &data)
{//返回树中某一结点的值

	if (index < 1 || index > m_maxIndex)
	{
		return TT_ERROR;
	}
	data = m_base[index - 1];
	return (data != 0 ? TT_OK : TT_ERROR);
}

ElementType FBTree::treeDepth()
{
	return (m_len == 0 ? 0 : static_cast <int>(log((double)m_maxIndex) / log(2.0) + 1) );
}
ElementType FBTree::treeRoot(ElementType &rootData) //求树根的值
{
	if (m_len != 0)
	{
		rootData = m_base[0];
		return TT_OK;
	}
	return TT_ERROR;

}

Status FBTree::treeLen()
{
	cout << "该树的个数为:" << m_len << endl;
}
ElementType FBTree::treeEmpty()
{
	return (m_len == 0);
}
Status FBTree::treeDestory()
{
	this->treeClear();
	m_base =nullptr;
	m_size = 0;
	if (!m_base && m_size == 0)
	{
		cout << "该树销毁成功!" << endl;
	}
	else
	{
		cout << "该树销毁失败!" << endl;
	}
}
Status FBTree::treeClear()
{
	delete m_base;
	m_maxIndex = m_len = 0;
	if (m_base && (m_maxIndex == 0) && (m_len == 0))
	{
		cout << "该树已被清空!" << endl;
	}
	else
	{
		cout << "该树清空失败!" << endl;
	}
}
ElementType FBTree::treeCreate(ElementType *array, int length)
{
	for (int i = 0; i < length; i++)
	{
		ElementType data = array[i]; //每一次循环都用data保存当前的元素
		int fatherData = 1;
		if (i != 0)
		{
			fatherData = array[(i + 1) / 2 - 1]; //记录该结点的双亲
		}
		if (fatherData == 0 && data != 0)//父节点不存在,子节点存在,结构错误
		{
			cout << "父节点不存在,子节点存在,结构错误" << endl;
			return TT_ERROR;
		}
		m_base[i] = data;   // 数据进入数组
		if (data != 0)
		{
			m_len++; //元素个数+1
			m_maxIndex = i + 1; // 索引值加1
		}

	}
	return TT_OK;

}

int main()
{
	int sizeCapacity(0);
	cout << "输入顺序二叉树的最大容量:";
	cin >> sizeCapacity;
	FBTree myFBTree(sizeCapacity);
	myFBTree.treeCreate(FBTree::fatherData, 20);
	while (true)
	{
		{
			cout << "*************************************************************" << endl
				<< "*******************   顺序二叉树的基本功能展示   *******************" << endl
				<< "*****************************************************************" << endl
				<< "********************   选择1——判断树是否为空.   **********************" << endl
				<< "********************   选择2——返回树的深度.   **********************" << endl
				<< "********************   选择3——获取某个结点的双亲.   **********************" << endl
				<< "********************   选择4——获取某个结点的左孩子.   **********************" << endl
				<< "********************   选择5——获取某个结点的右孩子.   **********************" << endl
				<< "*****************************************************************" << endl
				<< "********************   选择6——获取某个结点的左兄弟.   **********************" << endl
				<< "********************   选择7——获取某个结点的右兄弟.   **********************" << endl
				<< "********************   选择8——为树中某一结点赋值.   **********************" << endl
				<< "*********************  选择9——返回某一结点的值.  ************************" << endl
				<< "*****************************************************************" << endl
				<< "*********************  选择10——返回树根的值.  *****************" << endl
				<< "*********************  选择11——清空树.  *****************" << endl
				<< "*********************  选择12——销毁树.  *****************" << endl
				<< "*********************  选择13——插入字树.  *****************" << endl
				<< "*********************  选择14——删除字树.  *****************" << endl
				<< "*******************    选择15——清屏!      ************************" << endl
				<< "******************     选择0——退出程序!   ************************" << endl
				<< "***********************************************************************" << endl
				<< "***********************************************************************" << endl;
		}
		cout << "\n********************   请输入你想要使用的顺序表功能的序号   ***************" << endl;
		cout << "请输入你的选择:";
		int userChoice(0);
		cin >> userChoice;
		if (!userChoice)
		{
			cout << "程序已退出,感谢您的使用!" << "\n" << endl;
			break;
		}
		switch (userChoice)
		{
		case 1:
		{
			if (myFBTree.treeEmpty())  //判断是否为空
			{
				cout << "目前该顺序树为空!" << endl;
				myFBTree.treeLen();
			}
			else
			{
				cout << "目前顺序树非空!" << endl;
				myFBTree.treeLen();
				myFBTree.levelOrderTraverse();

			}
			break;
		}
		case 2:
		{
			if (int depht = myFBTree.treeDepth())
			{
				cout << "该树的深度为:" << depht << endl;
				myFBTree.treeLen();
			}
			else
			{
				cout << "该树的深度为空!" << endl;
			}
			break;
		}
		case 3:
		{
			cout << "输入你想获取哪个结点的双亲:(根结点无双亲!)";
			int getParent = 0;
			cin >> getParent;		
			if (int temp = myFBTree.treeParent(getParent))
			{
				cout << "该结点的双亲为:" << temp << endl;
			}
			else
			{
				cout << "输入错误,该结点无双亲!" << endl;
			}
			break;
		}
		case 4:
		{
			cout << "输入你想获取哪个结点的左孩子:(叶子结点无孩子!)";
			int getLetfChild = 0;
			cin >> getLetfChild;
			if (int temp = myFBTree.treeLeftChild(getLetfChild))
			{
				cout << "该结点的左孩子为:" << temp << endl;
			}
			else
			{
				cout << "该结点为叶节点,无左孩子!" << endl;
			}
			break;
		}
		case 5:
		{
			cout << "输入你想获取哪个结点的右孩子:(叶子结点无孩子!)";
			int getRightChild = 0;
			cin >> getRightChild;
			if (int temp = myFBTree.treeRightChild(getRightChild))
			{
				cout << "该结点的右孩子为:" << temp << endl;
			}
			else
			{
				cout << "该结点为叶节点,无右孩子!" << endl;
			}
			break;
		}
		case 6:
		{
			cout << "输入你想获取哪个结点的左兄弟:";
			int getLehtBrother = 0;
			cin >> getLehtBrother;
			if (int temp = myFBTree.treeLeftSibling(getLehtBrother))
			{
				cout << "该结点的左兄弟为:" << temp << endl;
			}
			else
			{
				cout << "该结点没有左兄弟!" << endl;
			}
			break;
		}
		case 7:
		{
			cout << "输入你想获取哪个结点的右兄弟:";
			int getRightBrother = 0;
			cin >> getRightBrother;
			if (int temp = myFBTree.treeRightSibling(getRightBrother))
			{
				cout << "该结点的右兄弟为:" << temp << endl;
			}
			else
			{
				cout << "该结点没有右兄弟!" << endl;
			}
			break;
		}
		case 8:
		{
			int overrideData(0);
			int indexLocition(0);  
			cout << "请输入你想要赋值的元素位置:";
			cin >> indexLocition;
			cout << "请输入你想要覆盖的值为:";
			cin >> overrideData;
			if (myFBTree.treeAssign(indexLocition, overrideData))
			{
				cout << "该结点赋值成功!" << endl;
				myFBTree.levelOrderTraverse();
			}
			else
			{
				cout << "该结点赋值失败!" << endl;
			}
			break;
		}
		case 9:
		{
			cout << "请输入你想返回哪个位置的值:";
			int temp = 0;
			int getValue = 0;
			cin >> getValue;
			if (myFBTree.treeValue(getValue, temp))
			{
				cout << "该位置的值为:" << temp << endl;
			}
			else
			{
				cout << "获取值失败,该位置没有值!" << endl;
			}
			break;
		}
		case 10:
		{
			int getRootValue = 0;
			if (myFBTree.treeRoot(getRootValue))
			{
				cout << "树根的值为:" << getRootValue << endl;
			}
			else
			{
				cout << "该树为空,没有树根的值!" << endl;
			}
			break;
		}
		case 11:
		{
			myFBTree.treeClear();
			myFBTree.treeLen();
			break;
		}
		case 12:
		{
			cout << "你确定要销毁该树吗?(若销毁请输入输入(Y/y))";
			char yesOrNo;
			cin >> yesOrNo;
			if ((yesOrNo == 'Y') || (yesOrNo == 'y'))
			{
				myFBTree.treeDestory();		
			}
			break;
		}
		case 13:
		{
			int sizeSubCapacity(0);
			cout << "输入顺序二叉树的字树的最大容量:";
			cin >> sizeSubCapacity;

			FBTree childTree(sizeSubCapacity);
			childTree.treeCreate(FBTree::childData, 10);
			childTree.levelOrderTraverse();

			cout << "请输入你想在哪个结点上插入一棵字树:";
			int pushDatas = 0;
			cin >> pushDatas;

			int childTemp = childTree.treeDepth();
			int farentTemp = myFBTree.treeDepth();
			myFBTree.treeInsertChild(pushDatas, true, childTemp, farentTemp, childTree);
			myFBTree.levelOrderTraverse();
			break;
		}	
		case 14:
		{
			cout << "请输入你想删除的字树位置:";
			int removeSubTree = 0;
			cin >> removeSubTree;
			myFBTree.treeDeleteChild(removeSubTree, true);
			myFBTree.levelOrderTraverse();
			break;
		}
		case 15:
			system("cls");
			cout << "屏幕已经清屏,可以重新输入!" << "\n" << endl;
			break;
		default:
			cout << "输入的序号不正确,请重新输入!" << "\n" << endl;
		}
	}
	system("pause");
	return 0;
}

                           

如果有错误的话,欢迎指教。


如果转载的话, 请指明出处。谢谢。

猜你喜欢

转载自blog.csdn.net/qq_34536551/article/details/84201301