数据结构之二叉树(类模板实现)(C++)


注:代码中使用的“ObjArrayList.h”、"SqStack.h"、"CQueue.h" 头文件代码在上三篇博文中已给出,分别为数据结构之顺序列表、栈、队列。

//文件名:"BiTree.h"
#pragma once
#ifndef BITREE_H_
#define BITREE_H_
#include <string>
#include "ObjArrayList.h"	//顺序表(对象元素)
#include "SqStack.h"		//顺序栈(对象元素),也可用链栈
#include "CQueue.h"			//循环队列(对象元素),也可用链队列
using namespace std;

/*
.	二叉树 类模板实现 BiTree (Binary Tree)
.	存储结构:二叉链表
.	遍历方式:先序遍历(Preoder Traversal)、中序遍历(InOrder Traversal)、后序遍历(PostOrder Traversal)
.	注:元素对象需实现 输出操作符 的重载,否则无法打印树结点!
*/

//二叉树结点类型
template <typename ElemType>
struct Node
{
	ElemType * data;			//数据域
	int seq;					//完全二叉树序号
	int level;					//层次
	int num;					//层次上的坐标序号(考虑空结点)
	Node<ElemType> * lchild;	//左子树指针域
	Node<ElemType> * rchild;	//右子树指针域
};

//非递归后序遍历结点类型(含标志位)
template <typename ElemType>
struct NodeTag
{
	Node<ElemType> *p;		//二叉树结点域
	int tag;				//结点访问次数标志域:1|访问一次  2|访问二次  -1|可销毁
};

template <typename ElemType>
class BiTree
{
private:
	Node<ElemType> *bt;		//树根指针
	/*
	.	注:深度高度值虽相同,但算法上有不同
	.		1.高度:自下而上求解
	.		2.深度:自上而下求解
	*/
	int height;				//二叉树高度(自下而上定义)
	int depth;				//二叉树深度(自上而下定义)

	Node<ElemType> * _PreOrderCreate_R(ObjArrayList<ElemType> *list, int &index, int seq);	//先序遍历递归构造树(对象型结点)
	void _PostOrderDestory_R(Node<ElemType> *p);			//后序遍历递归 销毁二叉树
	
	void _CreateCoordinate(Node<ElemType> *p, int seq);		//创建结点坐标
	int _PostOrderHelght_R(Node<ElemType> *p);								//后序遍历递归 求二叉树高度(自下而上求解)
	void _PostOrderDepth_R(Node<ElemType> *p, int level, int &depth);		//后序遍历递归 求二叉树深度(自上而下求解)
	
	int _PostOrderNodeCount_R(Node<ElemType> *p);			//后序遍历递归 求结点个数
	int _PostOrderLeafCount_R(Node<ElemType> *p);			//后序遍历递归 求叶子结点个数

	bool _PreOrderCompare_R(Node<ElemType> *p, Node<ElemType> *q);	//比较二叉树是否相同
	Node<ElemType> * _PreOrderCopy_R(Node<ElemType> *p);		//复制二叉树

	void _PreOrderDisplay_R(Node<ElemType> *p);				//先序遍历递归 解析二叉树
	void _InOrderDisplay_R(Node<ElemType> *p);				//中序遍历递归 解析二叉树
	void _PostOrderDisplay_R(Node<ElemType> *p);			//后序遍历递归 解析二叉树

public:
	BiTree() { this->bt = NULL; this->height = 0; this->depth = 0; };
	BiTree(ObjArrayList<ElemType> *list);	//有参构造
	~BiTree();					//析构函数:销毁二叉树

	int Helght();				//获取二叉树高度
	int Depth();				//获取二叉树深度

	int NodeCount();			//获取二叉树结点个数
	int LeafCount();			//获取二叉树叶子结点个数

	bool Compare(BiTree<ElemType> *t);		//比较二叉树是否相同
	BiTree<ElemType> *Copy();			//复制二叉树对象

	void PreOrderDisplay_R();	//先序遍历递归 解析二叉树
	void PreOrderDisplay();		//先序遍历非递归 解析二叉树

	void InOrderDisplay_R();	//中序遍历递归 解析二叉树
	void InOrderDisplay();		//中序遍历非递归 解析二叉树

	void PostOrderDisplay_R();	//后序遍历递归 解析二叉树
	void PostOrderDisplay();	//后序遍历非递归 解析二叉树

	void LevelOrderDisplay();			//层次遍历非递归 解析二叉树
	void LevelOrderDisplayStruct();		//层次遍历非递归 打印二叉树结构
};



template <typename ElemType>
BiTree<ElemType>::BiTree(ObjArrayList<ElemType> *list)
{
	//默认采用先序遍历顺序表构造二叉树
	int index = 0;
	int seq = 1;
	this->bt = _PreOrderCreate_R(list, index, seq);
	//利用后序遍历,从下而上求树高
	this->height = _PostOrderHelght_R(this->bt);
	//利用后序遍历,从上而下求树深
	int level = 1, depth = 0;
	_PostOrderDepth_R(this->bt, level, depth);
	this->depth = depth;
}

template <typename ElemType>
BiTree<ElemType>::~BiTree()
{
	/*
	.	销毁二叉树
	*/
	_PostOrderDestory_R(this->bt);
	cout << "二叉树已销毁!" << endl;
}

template <typename ElemType>
int BiTree<ElemType>::Helght()
{
	/*
	.	获取二叉树高度
	*/
	return this->height;
}

template <typename ElemType>
int BiTree<ElemType>::Depth()
{
	/*
	.	获取二叉树高度
	*/

	return this->depth;
}

template <typename ElemType>
int BiTree<ElemType>::NodeCount()
{
	/*
	.	获取二叉树结点个数
	*/
	return _PostOrderNodeCount_R(this->bt);
}

template <typename ElemType>
int BiTree<ElemType>::LeafCount()
{
	/*
	.	获取二叉树叶子结点个数
	*/
	return _PostOrderLeafCount_R(this->bt);
}

template <typename ElemType>
bool BiTree<ElemType>::Compare(BiTree<ElemType> *t)
{
	/*
	.	比较两棵树是否相同
	*/
	return _PreOrderCompare_R(this->bt, t->bt);
}

template <typename ElemType>
BiTree<ElemType> *BiTree<ElemType>::Copy()
{
	/*
	.	比较两棵树是否相同
	*/
	//初始化二叉树对象
	BiTree<ElemType> *t = new BiTree<ElemType>();
	//复制二叉树(对象数据,非对象地址)
	t->bt = _PreOrderCopy_R(this->bt);
	t->height = this->height;
	t->depth = this->depth;
	return t;
}

template <typename ElemType>
Node<ElemType> *BiTree<ElemType>::_PreOrderCreate_R(ObjArrayList<ElemType> *list, int &index, int seq)
{
	/*
	.	先序遍历递归创建二叉树
	.	入参:
	.		ObjArrayList<ElemType> *list : 先序遍历组合的对象结点顺序表
	.		int &index: 顺序表遍历索引
	.		int seq: 以完全二叉树,对每个结点排序
	.	出参:
	.		Node<ElemType> * : 树根结点指针
	.	注:以顺序表(对象元素结点)创建
	*/
	Node<ElemType> *p = NULL;
	//1.超出顺序表时返回,结束
	if (index >= list->Length())
	{
		return p;
	}
	//2.元素为 NULL 时,意为空结点
	else if (list->Get(index) == NULL)
	{
		return p;
	}
	//3.创建根结点,并递归创建其左右子树
	else
	{
		p = new Node<ElemType>;
		p->data = list->Get(index);
		_CreateCoordinate(p, seq);	//创建结点坐标
		p->lchild = _PreOrderCreate_R(list, ++index, 2 * seq);
		p->rchild = _PreOrderCreate_R(list, ++index, 2 * seq + 1);
	}
	return p;
}

template <typename ElemType>
void BiTree<ElemType>::_PostOrderDestory_R(Node<ElemType> *p)
{
	/*
	.	后序遍历 递归 销毁二叉树
	.	注:需先销毁子节点,再根结点
	*/
	if (p != NULL)
	{
		_PostOrderDestory_R(p->lchild);
		_PostOrderDestory_R(p->rchild);
		delete p;
	}
}

template <typename ElemType>
void BiTree<ElemType>::_CreateCoordinate(Node<ElemType> *p, int seq)
{
	/*
	.	创建结点坐标
	.	入参:
	.		Node<ElemType> *p: 树结点
	.		int seq: 完全二叉树的形式的结点序号
	*/
	p->seq = seq;	//结点序号(完全二叉树形式)
	p->level = (int)floor(log(seq) / log(2)) + 1;	//结点所在层次深度:floor( log2(seq) ) + 1;log2() 利用换底公式:log2(x) = log(x)/log(2)
	p->num = seq - (int)pow(2, p->level - 1) + 1;	//结点所在层次的结点位置序号:seq - 上层末尾结点序号(完全二叉树形式)
}

template <typename ElemType>
int BiTree<ElemType>::_PostOrderHelght_R(Node<ElemType> *p)
{
	/*
	.	后序遍历 递归求二叉树高度(自下而上)
	.	入参:
	.		1.Node<ElemType> *p: 树结点
	.	出参:
	.		1.int : 子树高度
	.	算法解析:
	.		1.求每颗子树的高度(左右子树高度取最大)
	.		2.叶子结点高度为 1
	*/
	int lheight = 0, rheight = 0;
	if (p != NULL)
	{
		lheight = _PostOrderHelght_R(p->lchild);
		rheight = _PostOrderHelght_R(p->rchild);
		return (lheight > rheight ? lheight : rheight) + 1;	//返回较大的一个树深 + 1 (根结点)
	}
	return 0;	//空结点返回 0
}

template <typename ElemType>
void BiTree<ElemType>::_PostOrderDepth_R(Node<ElemType> *p, int level, int &depth)
{
	/*
	.	后序遍历递归 求树深度(自上而下)
	.	入参:
	.		1.Node<ElemType> *p: 树结点
	.		2.int level: 树层次
	.		3.int &depth: 树深度
	.	算法解析:
	.		1.depth = max[ level(i) ]	, 其中i 为每一个根到叶的路径
	.		2.自上而下体现在:level 的逐层往下增加
	*/
	if (p != NULL)
	{
		_PostOrderDepth_R(p->lchild, level + 1, depth);
		_PostOrderDepth_R(p->rchild, level + 1, depth);
		//若为叶子节点,则一条根叶路径走完,比较深度
		//if (p->lchild == NULL && p->rchild == NULL)	//此判断多此一举,上层深度不可能比下层大
			if (level > depth)
				depth = level;
	}
}

template <typename ElemType>
int BiTree<ElemType>::_PostOrderNodeCount_R(Node<ElemType> *p)
{
	/*
	.	后序遍历递归 求树结点数
	*/
	if (p != NULL)
		return _PostOrderNodeCount_R(p->lchild) + _PostOrderNodeCount_R(p->rchild) + 1; //先左,后右,再返回相加结果,即为后序
	return 0;
}

template <typename ElemType>
int BiTree<ElemType>::_PostOrderLeafCount_R(Node<ElemType> *p)
{
	/*
	.	后序遍历递归 求树叶子结点数
	*/
	if (p != NULL)
	{
		if (p->lchild == NULL && p->rchild == NULL)
			return 1;
		else
			return _PostOrderLeafCount_R(p->lchild) + _PostOrderLeafCount_R(p->rchild); //先左,后右,再返回相加结果,即为后序
	}
	return 0;
}
template <typename ElemType>
bool BiTree<ElemType>::_PreOrderCompare_R(Node<ElemType> *p, Node<ElemType> *q)
{
	/*
	.	先序遍历递归 比较两颗二叉树是否相同
	*/
	if (p != NULL && q != NULL)
	{
		//先比较根结点元素(结点元素类需实现 Compare() 接口),后比较左右子树
		return (p->data->Compare(q->data))
			&& _PreOrderCompare_R(p->lchild, q->lchild) 
			&& _PreOrderCompare_R(p->rchild, q->rchild);
	}
	else if (p == NULL && q == NULL)
		return true;
	else
		return false;
}

template <typename ElemType>
Node<ElemType> * BiTree<ElemType>::_PreOrderCopy_R(Node<ElemType> *p)
{
	/*
	.	先序遍历递归 复制二叉树(实现复制对象数据,并非对象地址!!)
	*/
	Node<ElemType> *q = NULL;
	if (p != NULL)
	{
		q = new Node<ElemType>;
		q->data = p->data->Copy();	//结点元素类需实现 Copy() 接口!!
		q->lchild = _PreOrderCopy_R(p->lchild);
		q->rchild = _PreOrderCopy_R(p->rchild);
	}
	return q;
}

template <typename ElemType>
void BiTree<ElemType>::PreOrderDisplay_R()
{
	/*
	.	先序遍历递归显示二叉树
	*/
	cout << "The BiTree is: ";
	_PreOrderDisplay_R(this->bt);
	cout << endl;
}

template <typename ElemType>
void BiTree<ElemType>::_PreOrderDisplay_R(Node<ElemType> *p)
{
	/*
	.	先序遍历递归显示二叉树
	*/
	if (p != NULL)
	{
		cout << p->data << " ";
		_PreOrderDisplay_R(p->lchild);
		_PreOrderDisplay_R(p->rchild);
	}
	else
	{
		cout << "# ";	//空结点以 '#' 代替
	}
}

template <typename ElemType>
void BiTree<ElemType>::PreOrderDisplay()
{
	/*
	.	先序遍历 非递归 解析二叉树
	.	算法:(栈)
	.		1.先访问子树根结点,根结点入栈,然后访问左子树;
	.		2.等到子树根结点为空,出栈根结点,访问其右子树;
	.		3.如此循环...
	*/
	//树根结点
	Node<ElemType> *p = this->bt;
	//初始化栈,存放压栈结点
	SqStack<Node<ElemType>> *st = new SqStack<Node<ElemType>>(20);	//栈容量 需满足 二叉树深度减一
	/*	按照一般思路写出的代码,其中两个 while 可以合并,如下结果
	//子树根结点不为空,遍历整棵树
	while (p != NULL)
	{
		//1.输出子树根结点
		cout << p->data << " ";
		//2.入栈根结点(含NULL)(也可入栈右子树结点,但这样就不可输出 NULL 结点)
		st->Push(p);
		//3.指针 p 移到左子树结点
		p = p->lchild;
		//输出 左子树(NULL)结点
		if (p == NULL)
			cout << "# ";
		//4.若子树结点为空,且栈不为空
		while (p == NULL && !st->Empty())
		{
			//则出栈,且指针 p 移到出栈结点右子树上
			p = st->Pop();
			p = p->rchild;
			//输出 右子树(NULL)结点
			if (p == NULL)
				cout << "# ";
		}
	}
	*/
	cout << "The BiTree is: ";
	//子树根结点不为空,且栈不为空,遍历整棵树
	while (p != NULL || !st->Empty())
	{
		//1.子树根结点不为空
		if (p != NULL)
		{
			//1.输出子树根结点
			cout << p->data << " ";
			//2.入栈根结点(含NULL)(也可入栈右子树结点,但这样就不可输出 NULL 结点)
			st->Push(p);
			//3.指针 p 移到左子树结点
			p = p->lchild;			
		}
		//2.子树结点为空
		else
		{
			//则出栈,且指针 p 移到出栈结点右子树根上
			p = st->Pop();
			p = p->rchild;
		}
		//输出 子树(NULL)结点(左右)
		if (p == NULL)
			cout << "# ";
	}
	cout << endl;
	//释放栈
	delete st;
}

template <typename ElemType>
void BiTree<ElemType>::InOrderDisplay_R()
{
	/*
	.	中序遍历递归显示二叉树
	*/
	cout << "The BiTree is: ";
	_InOrderDisplay_R(this->bt);
	cout << endl;
}

template <typename ElemType>
void BiTree<ElemType>::_InOrderDisplay_R(Node<ElemType> *p)
{
	/*
	.	中序遍历递归显示二叉树
	*/
	if (p != NULL)
	{
		_InOrderDisplay_R(p->lchild);
		cout << p->data << " ";
		_InOrderDisplay_R(p->rchild);
	}
	else
	{
		cout << "# ";	//空结点以 '#' 代替
	}
}

template <typename ElemType>
void BiTree<ElemType>::InOrderDisplay()
{
	/*
	.	中序遍历 非递归 显示二叉树
	.	算法:(栈)
	.		1.先根结点入栈,然后访问左子树;
	.		2.等到子树根结点为空,出栈根结点,访问根结点,访问右子树;
	.		3.如此循环...
	*/
	//初始化根结点
	Node<ElemType> *p = this->bt;
	//初始化栈,存放压栈结点
	SqStack<Node<ElemType>> *st = new SqStack<Node<ElemType>>(20);	//栈容量 需满足 二叉树深度减一
	cout << "The BiTree is: ";
	//子树根结点不为空,且栈不为空,遍历整棵树
	while (p != NULL || !st->Empty())
	{
		//1.子树根结点不为空
		if (p != NULL)
		{
			//1.入栈根结点(含NULL)(也可入栈右子树结点,但这样就不可输出 NULL 结点)
			st->Push(p);
			//2.指针 p 移到左子树结点
			p = p->lchild;
		}
		//2.子树结点为空
		else
		{
			//1.则出栈
			p = st->Pop();
			//2.输出子树根结点
			cout << p->data << " ";
			//3.指针 p 移到出栈结点右子树根上
			p = p->rchild;
		}
		//输出 子树(NULL)结点(左右)
		if (p == NULL)
			cout << "# ";
	}
	cout << endl;
	//释放栈
	delete st;
}

template <typename ElemType>
void BiTree<ElemType>::PostOrderDisplay_R()
{
	/*
	.	后序遍历递归显示二叉树
	*/
	cout << "The BiTree is: ";
	_PostOrderDisplay_R(this->bt);
	cout << endl;
}

template <typename ElemType>
void BiTree<ElemType>::_PostOrderDisplay_R(Node<ElemType> *p)
{
	/*
	.	后序遍历递归显示二叉树
	*/
	if (p != NULL)
	{
		_PostOrderDisplay_R(p->lchild);
		_PostOrderDisplay_R(p->rchild);
		cout << p->data << " ";
	}
	else
	{
		cout << "# ";	//空结点以 '#' 代替
	}
}

template <typename ElemType>
void BiTree<ElemType>::PostOrderDisplay()
{
	/*
	.	后序遍历 非递归 显示二叉树
	.	算法:(栈)
	.		1.先入栈子树根结点(访问次数默认1),访问左子树结点;
	.		2.直到子树根结点为空,出栈根结点:
	.			2.1.若其访问次数为1,则标记其为2,并将其再入栈,访问其右子树;
	.			2.2.若其访问次数为2,则访问根结点;
	.		3.如此循环...
	.		注:也可每次入栈根结点、右子树结点,这样会比只入栈根结点多一倍的栈容量,但可不用区分栈中根结点第几次被访问
	*/
	//初始化根结点
	Node<ElemType> *p = this->bt;
	//初始化带标识位结点
	NodeTag<ElemType> *nt = NULL;
	//初始化栈,存放压栈结点
	SqStack<NodeTag<ElemType>> *st = new SqStack<NodeTag<ElemType>>(20);	//栈容量 需满足 二叉树深度减一
	cout << "The BiTree is: ";
	//子树根结点不为空,且栈不为空,遍历整棵树
	while (p != NULL || !st->Empty())
	{
		//1.子树根结点不为空
		if (p != NULL)
		{
			//0.创建带标识位的结点
			nt = new NodeTag<ElemType>;
			nt->p = p;		//赋值根结点
			nt->tag = 1;	//标识位初始默认 1
			//1.入栈根结点(带标识位)
			st->Push(nt);
			//2.指针 p 移到左子树根结点
			p = p->lchild;
		}
		//2.子树根结点为空
		else
		{
			//1.出栈根结点
			nt = st->Pop();
			//2.若第一次访问
			if (nt->tag == 1)
			{
				//1.置标识位 2 ,根结点再次入栈
				nt->tag = 2;
				st->Push(nt);
				//2.指针 p 移到右子树根结点
				p = nt->p->rchild;
			}
			//3.若第二次访问
			else
			{
				//输出根结点
				cout << nt->p->data << " ";
				//标记结点为可销毁 -1 状态
				nt->tag = -1;
			}
		}
		//输出 子树(NULL)结点(左右),且出栈根结点为可销毁(-1)状态
		if (p == NULL && nt->tag != -1)
			cout << "# ";
		//销毁 nt 指向的标志结点内存
		if (nt->tag == -1)
			delete nt;
		//置空 nt
		nt = NULL;	//置空
	}
	cout << endl;
	delete st;
}

template <typename ElemType>
void BiTree<ElemType>::LevelOrderDisplay()
{
	/*
	.	层次遍历 非递归 显示二叉树
	.	算法:(队列)
	.		1.将树根结点入队;
	.		2.出队结点,访问子树根结点,为空时输出"#",非空时输出结点,入队左、右子树;
	.		3.如此循环 2 ...
	.		注:两种结点访问时机:
	.			1.结点入队前:需分左右子树输出,代码不统一。
	.			2.结点出队后:统一由出队子树根结点输出,代码更统一。(此处采用)
	*/
	//初始化队列
	CQueue<Node<ElemType>> *cq = new CQueue<Node<ElemType>>(20);	//入队容量 需满足 结点数最多的一层( <= 取最深层叶子节点数 (2^n - 1) )
	//初始化结点指针
	Node<ElemType> *p = NULL;

	cout << "The BiTree is: ";
	if (this->bt == NULL)
		return;
	//1.入队根结点
	cq->EnQueue(this->bt);
	//2.循环出队,访问子树
	while (!cq->isEmpty())
	{	
		//1.出队 子树根结点
		p = cq->DeQueue();
		//1.1.为空:输出 "#"
		if (p == NULL)
			cout << "# ";
		//1.2.非空:访问子树
		else
		{
			//1.访问根结点
			cout << p->data << " ";
			//2.入队 左子树
			cq->EnQueue(p->lchild);
			//3.入队 右子树
			cq->EnQueue(p->rchild);
		}
	}
	cout << endl;
	delete cq;
}

template <typename ElemType>
void BiTree<ElemType>::LevelOrderDisplayStruct()
{
	/*
	.	层次遍历 非递归 打印二叉树结构(含结点坐标信息)
	.	结点坐标信息:
	.		1.seq		: 完全二叉树序号
	.		2.level		: 层次
	.		3.num		: 层次上的坐标序号(考虑空结点)
	.	算法:(队列)
	.		1.访问根结点,将其入队;
	.		2.出队结点,先访问左子树(非空时输出、入队,空时输出 "#"),后访问右子树(非空时输出、入队,空时输出 "#");
	.		3.如此循环 2 ...
	.		注:两种结点访问时机:
	.			1.结点入队前:需分左右子树输出,代码不统一,但是可以由出队结点确定其下子树 NUlL 的层次。(此处采用)
	.			2.结点出队后:统一由出队子树根结点输出,代码更统一。
	.
	.	注:目前还是实现不了结点位置的准确输出---!!!
	.	(想法:再实现一个坐标类,可将结点坐标输进去,就能显示了)
	*/
	//初始化队列
	CQueue<Node<ElemType>> *cq = new CQueue<Node<ElemType>>(20);	//入队容量 需满足 结点数最多的一层( <= 取最深层叶子节点数 (2^n - 1) )
	//初始化结点指针
	Node<ElemType> *p = NULL, *q = NULL;
	//初始化树层次
	int level = 1;
	//初始化标记
	int tag = -1;	// -1|队列出队  0|访问右子树  1|访问左子树

	cout << "The BiTree Struct is: " << endl;
	if (this->bt == NULL)
		return;
	//1.访问根结点,将其入队
	cout << this->bt->data << " ";
	cq->EnQueue(this->bt);
	//2.循环出队,访问子树
	while (!cq->isEmpty() || tag != -1)
	{
		//标记:出队
		if (tag == -1)
		{
			//1.出队 子树根结点
			p = cq->DeQueue();
			//如果 p->level + 1 > level ,则转为下一层
			if (p->level + 1 > level)
			{
				level = p->level + 1;	//出队元素层次 + 1,即为当前层次
				cout << endl;
			}
			tag = 0;	//将标记置为 0
			continue;	//进入下一次循环
		}
		//标记:访问左子树
		else if (tag == 0)
		{
			q = p->lchild;
			tag = 1;	//将标记置为 1
		}
		//标记:访问右子树
		else
		{
			q = p->rchild;
			tag = -1;	//将标记置为 -1
		}
		
		//访问子树结点
		if (q == NULL)
			cout << "# ";
		else
		{
			//1.1.访问子树结点
			cout << q->data << "_(" << q->seq << "," << q->level << "," << q->num << ") ";
			//1.2.入队 子树
			cq->EnQueue(q);
		}
	}
	cout << endl;
	delete cq;
}

#endif // !BITREE_H_
//文件名:"BiTree_Test.cpp"
#include "stdafx.h"
#include <iostream>
#include "BiTree.h"
#include "ObjArrayList.h"
using namespace std;

//树结点元素
struct Element
{
	char a;
	int b;
public:
	bool Compare(Element *p)
	{
		/*
		.	实现元素对象比较接口
		*/
		return a == p->a;
	}
	Element *Copy()
	{
		/*
		.	实现元素对象复制接口
		*/
		Element *p = new Element;
		p->a = a;
		p->b = b;
		return p;
	}
	friend ostream & operator <<(ostream& out, Element *p)
	{
		/*
		.	友元函数重载输出操作符,实现对象输出
		*/
		out << "(" << p->a << "," << p->b << ")";
		return out;
	}
};

int mian()
{
	cout << endl << "----------------------测试1.1.-------------------------" << endl;
	//1.1.测试 元素对象 输出
	Element *e = new Element{ 'A',1 };
	cout << "对象:" << e << endl;

	cout << endl << "----------------------测试1.2.-------------------------" << endl;
	//1.2.以 先序遍历的结点顺序 存放元素结点于 顺序列表 中
	//.................012345678901234
	//先序遍历字符串:"ABC##DE#G##F###";	//15个字符
	ObjArrayList<Element> *list = new ObjArrayList<Element>(15);
	list->Add(0, new Element{ 'A',1 });
	list->Add(1, new Element{ 'B',2 });
	list->Add(2, new Element{ 'C',3 });
	list->Add(3, NULL);
	list->Add(4, NULL);
	list->Add(5, new Element{ 'D',4 });
	list->Add(6, new Element{ 'E',5 });
	list->Add(7, NULL);
	list->Add(8, new Element{ 'G',7 });
	list->Add(9, NULL);
	list->Add(10, NULL);
	list->Add(11, new Element{ 'F',6 });
	list->Add(12, NULL);
	list->Add(13, NULL);
	list->Add(14, NULL);

	cout << endl << "----------------------测试1.3.-------------------------" << endl;
	//1.3.测试 顺序列表 输出
	cout << "顺序表长度:" << endl << list->Length() << " ;顺序表大小:" << list->Size() << endl;
	cout << "顺序表输出:" << endl << list << endl;

	cout << endl << "----------------------测试2.1.-------------------------" << endl;
	//2.1.测试 创建二叉树(先序遍历)
	BiTree<Element> *t = new BiTree<Element>(list);

	cout << endl << "----------------------测试2.2.-------------------------" << endl;
	//2.2.测试 显示二叉树(先序、中序、后续遍历)
	cout << "二叉树 先序遍历 递归 输出:" << endl;
	t->PreOrderDisplay_R();
	cout << "二叉树 先序遍历 非递归 输出:" << endl;
	t->PreOrderDisplay();
	cout << "二叉树 中序遍历 递归 输出:" << endl;
	t->InOrderDisplay_R();
	cout << "二叉树 中序遍历 非递归 输出:" << endl;
	t->InOrderDisplay();
	cout << "二叉树 后序遍历 递归 输出:" << endl;
	t->PostOrderDisplay_R();
	cout << "二叉树 后序遍历 非递归 输出:" << endl;
	t->PostOrderDisplay();
	cout << "二叉树 层次遍历 非递归 输出:" << endl;
	t->LevelOrderDisplay();

	cout << endl << "----------------------测试2.3.-------------------------" << endl;
	//2.3.测试 树属性
	cout << "二叉树高度:" << t->Helght() << ";二叉树深度:" << t->Depth() << endl;
	cout << "二叉树结点数:" << t->NodeCount() << ";二叉树叶子结点数:" << t->LeafCount() << endl;

	cout << endl << "----------------------测试2.4.-------------------------" << endl;
	//2.4.测试 二叉树两两比较
	ObjArrayList<Element> *list1 = new ObjArrayList<Element>(15);
	list1->Add(0, new Element{ 'A',1 });
	list1->Add(1, new Element{ 'B',2 });
	list1->Add(2, new Element{ 'C',3 });
	list1->Add(3, NULL);
	list1->Add(4, NULL);
	list1->Add(5, new Element{ 'D',4 });
	list1->Add(6, new Element{ 'E',5 });
	list1->Add(7, NULL);
	list1->Add(8, new Element{ 'G',7 });
	list1->Add(9, NULL);
	list1->Add(10, NULL);
	list1->Add(11, new Element{ 'F',6 });
	list1->Add(12, NULL);
	list1->Add(13, NULL);
	list1->Add(14, NULL);
	BiTree<Element> *t1 = new BiTree<Element>(list1);
	cout << "t 与 t1 两颗二叉树是否相同:" << (t->Compare(t1) ? "是" : "否") << endl;
	//更改二叉树 t1 结点 后再比较
	list1->Get(11)->a = 'H';
	cout << "修改 t1 节点后,两颗二叉树是否相同:" << (t->Compare(t1) ? "是" : "否") << endl;

	cout << endl << "----------------------测试2.5.-------------------------" << endl;
	//2.5.测试 二叉树复制
	BiTree<Element> *t2 = t->Copy();
	cout << "复制的二叉树 t2 与原二叉树 t 比较是否相同:" << (t->Compare(t2) ? "是" : "否") << endl;

	cout << endl << "----------------------测试2.6.-------------------------" << endl;
	//2.6.测试 以二叉树结构输出
	t->LevelOrderDisplayStruct();

	cout << endl << "----------------------测试2.7.-------------------------" << endl;
	//2.7.测试 二叉树销毁
	delete t;
	delete t1;
	delete t2;
	
	return 0;
}


猜你喜欢

转载自blog.csdn.net/weixin_39469127/article/details/80490104