【数据结构】 实验报告10 顺序、链式存储结构的二叉树递归遍历、层次遍历求高度

一、实验目的和要求 (源码在最后

要求:
两种及以上存储结构(建议 顺序存储结构和链式存储结构各一)、两种及以上方法(建议 递归遍历和层次遍历方法各一)。分析各代码性能。
抽象数据类型(二叉树)独立模块实现。
其它要求同作业-01要求。

二、实验环境

软件环境:visual stdio 2017
硬件环境:①CPU:Intel(R)Core(TM)i7-8565U CPU @1.80Ghz
②内存:8.0GB

三、实验内容

设计算法并实现求解二叉树高度(深度)。

四、实验过程

4.1 任务定义和问题分析

本次实验需要解决的问题主要为一下三个问题:数据结构的构建,递归遍历的实现,层次遍历的实现。

4.2 数据结构的选择和概要设计

方案一:
顺序存储结构,用一个数组记录二叉树结点值,数组下标记录二叉树编号(下标从1开始用)。递归遍历直接递归,层次遍历直接按层以编号顺序将编号与值一并输出。最终求得高度。
方案二:
链式存储结构,用结构体记录二叉树各结点。递归遍历直接递归,层次遍历以队列为辅助工具,不断入队,出队,达到层次遍历的目的。最终求得高度。

4.3 详细设计

方案一:
①数据结构的构建:
设计成一个class,其中负责记录结点值的数组,其下标为1记录根值,一般的,对于整数i,第2i位(如果存在)为第i位左子结点,2i+1位(如果存在)为第i位右子结点。
②递归遍历的实现:
设计一个递归函数,传入参数为结点标记值i(缺省值为1)其终止条件为:第i位对应结点不存在,返回0。其他情况每次返回各子树的左子树长度和右子树长度的最大值+1。

int GetlengthByRecursion(int i = 1)
	{
		if (i > totalnum || array[i] == ' ') return 0;
		return max(GetlengthByRecursion(2 * i), GetlengthByRecursion(2 * i + 1)) + 1;
	}

③层次遍历的实现:
循环输出各层,即输出各层数组值,同时得到二叉树的高度。

方案二:
①数据结构的构建:
设计成一个struct,内有data记录结点值,leftson指针作为左儿子结点指针,rightson指针作为右儿子结点指针。
②递归遍历的实现:
设计一个递归函数,思路同方案一。
③层次遍历的实现:
先定义好一个队列(同样采用链式结构),该队列用来作为二叉树结点的储存结构。先让根结点入队,之后进入一个循环:以len记录当前队列长度,再次进入循环:循环从1->len,队列头元素出队,记为node,输出node结点的数据,再将node的左儿子、右儿子依次入队。
这样,一个大循环中的小循环便是以层的形式,输出一个二叉树。每进行一次这样的循环,二叉树的高度便+1。

五、测试及结果分析

5.1 实验数据

在这里插入图片描述

以该二叉树来测试算法是否有效。

5.2 结果及分析

在这里插入图片描述

(中序遍历,先序遍历,后序遍历,这些是实验中的中间产物,保留下来,没有去除)
实验后分析:在采用顺序结构存储二叉树时,具有明显的问题:若二叉树不是完全二叉树形式,为了保持结点之间的关系,不得不空出许多元素来,这就造成了空间的浪费。在极端情况下,仅有n个结点的二叉树,却需要2^n-1个元素空间,这显然是不能接受的。顺序存储结构的优点在于其遍历较快,当然,这也需要在二叉树是完全二叉树时才能体现出来。
而链式存储结构,我们不需要关心二叉树是否为完全二叉树,因为链式存储结构本身的递归特性,其对每一个结点的操作都是相同的。
因此,我认为,在建立一般的二叉树时采用链式结构较为方便,建立完全二叉树时采用顺序存储结构更为方便。

六、实验收获

通过本次实验,加深了我对二叉树的理解,让我学会了如何构建一个二叉树,同时也对顺序结构与链式结构的优缺点理解更深。编程水平也得到了一定的提升。

七、附录(源代码)

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

//顺序存储结构
template<typename T>
class SeqBT
{
public:
	SeqBT(int totalnum)      
	{
		if (totalnum > 0)
		{
			this->totalnum = totalnum;
			array = new T[totalnum + 1];
			memset(array, ' ', (totalnum + 1) * sizeof(T));
		}
		
	}
	~SeqBT()
	{
		delete[]array;
	}
	void insert(int num, T data)
	{
		if (num <= totalnum)
			array[num] = data;
	}
	int GetlengthByRecursion(int i = 1)
	{
		if (i > totalnum || array[i] == ' ') return 0;
		return max(GetlengthByRecursion(2 * i), GetlengthByRecursion(2 * i + 1)) + 1;
	}
	int GetlengthByLevel()
	{
		int length = 0;
		for (; pow(2.0, length+1) - 1 <= totalnum; length++)
		{
			cout << "第" << length + 1 << "层的元素为:";
			for (int i = pow(2.0, length); i <= pow(2.0, length + 1) - 1; i++)
				cout << i << ":" << array[i] << " ";
			cout << endl;
		}
		return length;
	}
private:
	int totalnum;
	T* array;
};
//链式存储结构
template<typename T>
struct TreeNode
{
	T data;
	TreeNode<T>* leftson;
	TreeNode<T>* rightson;
	TreeNode()
	{
		leftson = NULL;
		rightson = NULL;
	}
};
//二叉树结点链表(用于队列)
template<typename T>
struct Node
{
	TreeNode<T>* data;
	Node* next;
	Node()
	{
		data = NULL;
		next = NULL;
	}
};
//层次遍历需要用到的队列(简单设计)
template<typename T>
class queue
{
public:
	queue()
	{
		head = new Node<T>;
		rear = head;
		length = 0;
	}
	int getlength()
	{
		return length;
	}
	void push(TreeNode<T>* a)
	{
		Node<T>* s = new Node<T>;
		rear->next = s;
		s->data = a;
		rear = s;
		length++;
	}
	void pop(TreeNode<T>* & a)
	{
		Node<T>* s = new Node<T>;
		s = head->next;
		a = s->data;
		head->next = s->next;
		delete s;
		if (head->next == NULL)
		{
			rear = head;
		}
		length--;
	}
private:
	Node<T>* head;
	Node<T>* rear;
	int length;
};
//中序遍历算法
template<typename T>
void Inorder(TreeNode<T>*tree)
{
	if (tree == NULL) return;
	if (tree->leftson != NULL)
		Inorder(tree->leftson);
	cout << tree->data << " ";
	if (tree->rightson != NULL)
		Inorder(tree->rightson);
}
//先序遍历算法
template<typename T>
void Preorder(TreeNode<T>*tree)
{
	if (tree == NULL)  return;
	cout << tree->data << " ";
	if (tree->leftson != NULL)
		Preorder(tree->leftson);
	if (tree->rightson != NULL)
		Preorder(tree->rightson);
}
//后续遍历算法
template<typename T>
void Postorder(TreeNode<T>*tree)
{
	if (tree == NULL) return;
	if (tree->leftson != NULL)
		Postorder(tree->leftson);
	if (tree->rightson != NULL)
		Postorder(tree->rightson);
	cout << tree->data << " ";
}
//递归遍历求高度算法
template<typename T>
int GetlengthByRecursion(TreeNode<T>*tree)
{
	if (tree == NULL)
		return 0;
	return max(GetlengthByRecursion(tree->leftson), GetlengthByRecursion(tree->rightson)) + 1;
}
//层次遍历求高度算法
template<typename T> 
int GetlengthByLevel(TreeNode<T>* tree)
{
	queue<T> Queue;
	Queue.push(tree);
	int length = 0;
	while (Queue.getlength()!=0)
	{   
		cout << "第" << length + 1 << "层元素:";
		int len = Queue.getlength();
		for (int i = 1; i <= len; i++)
		{
			TreeNode<T>* node;
			Queue.pop(node);
			cout << node->data << " ";
			if (node->leftson != NULL)    Queue.push(node->leftson);
			if (node->rightson != NULL)   Queue.push(node->rightson);	
		}
		cout << endl;
		length++;
		
	}
	return length;
}
int main()
{
	//顺序存储结构的二叉树的创建
	cout << "顺式存储结构:" << endl;
	SeqBT<char> sequenceBT(15);
	sequenceBT.insert(1, 'A');
	sequenceBT.insert(2, 'B');
	sequenceBT.insert(3, 'E');
	sequenceBT.insert(4, 'C');
	sequenceBT.insert(5, 'D');
	sequenceBT.insert(7, 'F');
	sequenceBT.insert(14, 'G');
	//递归遍历
	cout << "递归遍历求高度:" << endl;
	cout << sequenceBT.GetlengthByRecursion() << endl;
	//层次遍历
	cout << "层次遍历求高度:" << endl;
	cout << sequenceBT.GetlengthByLevel();

	for (int i = 0; i <= 4; i++) cout << endl;


	//链式存储结构的二叉树的创建
	cout << "链式存储结构:" << endl;
	TreeNode<char>A, B, C, D, E, F, G;
	A.data = 'A';
	B.data = 'B';
	C.data = 'C';
	D.data = 'D';
	E.data = 'E';
	F.data = 'F';
	G.data = 'G';
	A.leftson = &B;
	A.rightson = &E;
	B.leftson = &C;
	B.rightson = &D;
	E.rightson = &F;
	F.leftson = &G;
	TreeNode<char>*root = &A;
	//中序遍历
	cout << "中序遍历:";
	Inorder(root);
	cout << endl;
	//先序遍历
	cout << "先序遍历:";
	Preorder(root);
	cout << endl;
	//后序遍历
	cout << "后序遍历:";
	Postorder(root);
	cout << endl;
	//递归遍历
	cout << "递归遍历求得高度为:";
	cout << GetlengthByRecursion(root) << endl;
    //层次遍历
	cout << "对二叉树进行层次遍历并得到高度:" << endl;
	cout << GetlengthByLevel(root) << endl;

}

猜你喜欢

转载自blog.csdn.net/RealCoder/article/details/105930600