注:代码中使用的“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; }