一、实验要求
<1>打印出二叉树的三种遍历序。
<2>设计算法按中序次序输出二叉树中各结点的值及其所对应的层次数。
<3>求二叉树的高度。
<4>求二叉树的结点数。
<5>求二叉树的叶子结点数。
<6>求二叉树的度为2的结点数。
<7>键盘输入一个元素x,求其父节点、兄弟结点、子结点的值,不存在时给出相应提示信息。对兄弟结点和孩子结点,存在时要明确指出是左兄弟、左孩子、右兄弟或右孩子。
<8>键盘输入一个元素x,求其在树中的层次。不存在时给出相应提示信息。
<9>将按顺序方式存储在数组中的二叉树转换为二叉链表形式。(数组中要扩展为完全二叉树)。
<10>交换二叉树中每个结点的左右孩子指针的值。(即:左子树变为右子树,右子树变为左子树)。
<11>复制一棵二叉树T到T1。(选做题)
<12>输出二叉树从每个叶子结点到根结点的路径。(选做题)
<13>对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印。(选做题)
<14>对二叉链表表示的二叉树,求2个结点最近的共同祖先。(选做题)
<15>求二叉树中一条最长的路径长度(边数),并输出路径上的个结点值。(选做题)
二、数据结构设计
template<class ElementType>
struct Node{
ElementType data; //数据域
struct Node * lchild; //左孩子指针
struct Node * rchild; //右孩子指针
};
//二叉树的封装如下:
template<class ElementType>
class BiTree{
public:
//初始化
BiTree(Node <ElementType> *&T);
//销毁树
void destory(Node <ElementType> *&pBT);
//二叉树操作菜单
static void menu();
//从文件读取数据
bool ReadFileToArray(char fileName[],char strLine[100][3],int & nLen);
//从文件创建二叉树
bool CreatBiTreeFromFile(Node<ElementType>*&pBT,char strLine[100][3],int nLen,int & nRow);
//创建子树函数
void createSubTree(Node <ElementType> * p,int k);
//创建二叉树函数
void createBiTree(Node <ElementType> *&T);
//先序遍历算法
void perOrderTraverse(Node <ElementType> * T);
//中序遍历算法
void inOrderTraverse(Node <ElementType> * T);
//后序遍历算法
void postOrderTraverse(Node <ElementType> * T);
//中序次序输出二叉树中各结点的值及其所对应的层次数
void outOrderTraverse(Node <ElementType> * T,int level);
//求树的高度
int BiTreeDepth(Node <ElementType> * T);
//求二叉树的结点数
void GetNodeNumber(Node <ElementType> * T,int &nNodeNum);
//求二叉树的叶子结点数
void leafNodeNum(Node <ElementType> *T,int &nNodeNum);
//求二叉树的度为2的结点数
void TwoBranchNodeNum(Node <ElementType> *T,int &nNodeNum);
//键盘输入一个元素x,求其父节点、兄弟结点、子结点的值,不存在时给出相应提示信息。对兄弟结点和孩子结点,存在时要明确指出是左兄弟、左孩子、右兄弟或右孩子
void GetFatherBrotherChildNode(Node <ElementType> *T,ElementType x);
//键盘输入一个元素x,求其在树中的层次。不存在时给出相应提示信息
void GetNodeLevel(Node <ElementType> *T,ElementType x,int level,int &flag);
//将按顺序方式存储在数组中的二叉树转换为二叉链表形式。(数组中要扩展为完全二叉树)
void ArrayToBiTree(Node <ElementType> *&T,ElementType A[],int i,int num);
//交换二叉树中每个结点的左右孩子指针的值
void ExchangeTree(Node <ElementType> * & T)
//二叉树转数组
void BiTreeToArray(Node <ElementType> *T,ElementType A[],int i,int &count);
//输出二叉树从每个叶子结点到根结点的路径
void PrintRoute(Node <ElementType> *T,ElementType path[],int pathLen);
//对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印
void LevelTraverse(Node <ElementType> *T,ElementType B[],int num);
//遍历查找节点x,并把路径保存在栈s中
void SearchBiTree(Node <ElementType> * T,Stack <Node <ElementType> * > & s,
ElementType x)
//求二叉树中一条最长的路径长度(边数),并输出路径上的结点值
void PrintMaxLenPath(Node <ElementType> *T,int MaxLen);
//非递归输出二叉树从每个叶子结点到根结点的路径(选做题)
void PrintAllPath(Node <ElementType> *T);
private:
Node<ElementType> *pBT; //根节点指针
};
三、算法设计
- 设计算法按中序次序输出二叉树中各结点的值及其所对应的层次数
算法思想:改造中序遍历算法,增加一个计算层次的变量level,初始化为1。每次访问根节点并输出结点的值和层数,每次递归调用时level++。
2.求二叉树的叶子结点数
算法思想:改造前序、中序、后序遍历算法,增加一个计算结点数的变量NodeNum,每次访问根节点时,如果T的没有左孩子和右孩子,NodeNum++。
3.键盘输入一个元素x,求其父节点、兄弟结点、子结点的值,不存在时给出相应提示信息。对兄弟结点和孩子结点,存在时要明确指出是左兄弟、左孩子、右兄弟或右孩子
算法思想:改造前序、中序、后序遍历算法,键盘输入一个元素x,判断T->lchild->data==x或T->rchild->data==x,如果相等,再判断是否有左右孩子T->lchild->lchild==NULL和T->lchild->rchild==NULL或T->rchild->lchild==NULL或T->rchild->rchild==NULL,如果存在,则输出父节点T->data,左兄弟T->lchild->data或右兄弟T->rchild->data,左孩子T->lchild->lchild->data或T->rchild->lchild->data,右孩子T->lchild->lchild->data或T->rchild->rchild->data。
4.键盘输入一个元素x,求其在树中的层次。不存在时给出相应提示信息
算法思想:改造前序、中序、后序遍历算法,增加一个计算层次的变量level,初始化为1。每次访问根节点时,如果T->data==x,则输出level即可。每次递归调用时level++。
5.将按顺序方式存储在数组中的二叉树转换为二叉链表形式。(数组中要扩展为完全二叉树)
算法思想:改造二叉树的一种遍历算法完成,这里改造先序遍历实现。算法包括两个整型参数i和num。i为结点在完全二叉树上的编号,从1开始;num为二叉树上最后有效结点编号。
6.交换二叉树中每个结点的左右孩子指针的值。(即:左子树变为右子树,右子树变为左子树)
算法思想:改造二叉树的一种遍历算法完成,每次访问根节点时,互换左右孩子指针即可。
7.复制一棵二叉树T到T1
算法思想:将二叉树T转换为数组,再将数组还原成二叉树T1
8.输出二叉树从每个叶子结点到根结点的路径(经历的结点)
算法思想:改造二叉树的非递归形式的后序遍历,如果p为根节点,遍历输出栈内元素,直到右子树遍历完成。
9.对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印。
算法思想:设一个数组A[]初始化为0,将二叉树转化为数组存入A数组中,在控制数组A的树形输出即可。
10.对二叉链表表示的二叉树,求2个结点最近的共同祖先
算法思想:把两个节点到根节点的路径分别保存到两个栈中,栈元素个数多的出栈,直到第一次两个栈中的栈顶元素相等且栈中元素个数相等。即栈顶元素为两个根节点的祖先。
11.求二叉树中一条最长的路径长度(边数),并输出路径上的个结点值
算法思想:先用递归求出树的高度,再用改造后序遍历的非递归算法,如果栈中的元素个数等于输的高度,输出栈内元素,继续遍历直到右子树遍历完成。
四、代码实现
#ifndef _SEQSTACK_H_
#define _SEQSTACK_H_
#include <iostream>
#define MAXLEN 100
using namespace std;
template<class ElementType>
class Stack{
public :
Stack(); //初始化栈
~Stack(); //销毁栈
int empty(); //判断栈是否为空
int pop(ElementType & x); //出栈
int push(ElementType x); //压栈
ElementType top(); //取栈顶元素
ElementType getData(int i); //获取第i个数据
int getLen(); //获取栈长度
private :
ElementType * data; //栈数据储存
int len; //栈当前元素个数
// int size; //栈的大小
};
//构造函数,初始化栈
template<class ElementType>
Stack<ElementType>::Stack()
{
data=new ElementType[MAXLEN];
len=0;
}
//析构函数,销毁栈
template<class ElementType>
Stack<ElementType>::~Stack()
{
delete [] data;
}
//判断栈是否为空
template<class ElementType>
int Stack<ElementType>::empty()
{
if(len==0)
{
return 1;
}
else{
return 0;
}
}
//出栈,成功返回1,否则返回0
template<class ElementType>
int Stack<ElementType>::pop(ElementType & x)
{
if(len==0)
{
return 0;
}
else{
x=data[len-1];
len--;
return 1;
}
}
//压栈
template<class ElementType>
int Stack<ElementType>::push(ElementType x)
{
if(len==MAXLEN)
{
return 0;
}
else{
len++;
data[len-1]=x;
return 1;
}
}
//取栈顶元素
template<class ElementType>
ElementType Stack<ElementType>::top()
{
if(empty())
{
return NULL;
}
else{
return data[len-1];
}
}
//遍历栈
template<class ElementType>
ElementType Stack<ElementType>::getData(int i)
{
return data[i];
}
//获取栈长度
template<class ElementType>
int Stack<ElementType>::getLen()
{
return len;
}
#endif // _SEQSTACK_H_
#ifndef _BITREE_H_
#define _BITREE_H_
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include "seqStack.h"
#include <cmath>
using namespace std;
template<class ElementType>
struct Node{
ElementType data; //数据域
struct Node * lChild; //左孩子指针
struct Node * rChild; //右孩子指针
};
template<class ElementType>
class BiTree{
public:
BiTree(Node <ElementType> *&T); //初始化
void destory(Node <ElementType> *&pBT); //销毁树
static void menu(); //二叉树操作菜单
bool ReadFileToArray(char fileName[],char strLine[100][3],int & nLen); //从文件读取数据
bool CreatBiTreeFromFile(Node<ElementType> *&pBT,char strLine[100][3],int nLen,int & nRow); //从文件创建二叉树
void createSubTree(Node <ElementType> * p,int k); //创建子树函数
void createBiTree(Node <ElementType> *&T); //创建二叉树函数
void perOrderTraverse(Node <ElementType> * T); //先序遍历算法
void inOrderTraverse(Node <ElementType> * T); //中序遍历算法
void postOrderTraverse(Node <ElementType> * T); //后序遍历算法
void outOrderTraverse(Node <ElementType> * T,int level); //中序次序输出二叉树中各结点的值及其所对应的层次数
int BiTreeDepth(Node <ElementType> * T); //求树的高度
void GetNodeNumber(Node <ElementType> * T,int &nNodeNum); //求二叉树的结点数
void leafNodeNum(Node <ElementType> *T,int &nNodeNum); //求二叉树的叶子结点数
void TwoBranchNodeNum(Node <ElementType> *T,int &nNodeNum); //求二叉树的度为2的结点数
void GetFatherBrotherChildNode(Node <ElementType> *T,ElementType x); //键盘输入一个元素x,求其父节点、兄弟结点、子结点的值,不存在时给出相应提示信息。对兄弟结点和孩子结点,存在时要明确指出是左兄弟、左孩子、右兄弟或右孩子
void GetNodeLevel(Node <ElementType> *T,ElementType x,int level,int &flag); //键盘输入一个元素x,求其在树中的层次。不存在时给出相应提示信息
void ArrayToBiTree(Node <ElementType> *&T,ElementType A[],int i,int num); //将按顺序方式存储在数组中的二叉树转换为二叉链表形式。(数组中要扩展为完全二叉树)
void ExchangeTree(Node <ElementType> *&T); //交换二叉树中每个结点的左右孩子指针的值
void BiTreeToArray(Node <ElementType> *T,ElementType A[],int i,int &count); //二叉树转数组
void PrintRoute(Node <ElementType> *T,ElementType path[],int pathLen); //输出二叉树从每个叶子结点到根结点的路径
void LevelTraverse(Node <ElementType> *T,ElementType B[],int num); //对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印
void SearchBiTree(Node <ElementType> *T,Stack<Node <ElementType> *> &s,ElementType x); //遍历查找节点x,并把路径保存在栈s中
void PrintMaxLenPath(Node <ElementType> *T,int MaxLen); //求二叉树中一条最长的路径长度(边数),并输出路径上的结点值
void PrintAllPath(Node <ElementType> *T); //非递归输出二叉树从每个叶子结点到根结点的路径(选做题)
private:
Node<ElementType> *pBT; //根节点指针
};
//初始化
template<class ElementType>
BiTree<ElementType>::BiTree(Node <ElementType> *&T)
{
pBT=T;
}
//销毁树
template<class ElementType>
void BiTree<ElementType>::destory(Node <ElementType> *&pBT)
{
if(pBT)
{
destory((pBT)->lChild);
destory((pBT)->rChild);
delete pBT;
}
}
//二叉树操作菜单
template<class ElementType>
void BiTree<ElementType>::menu()
{
cout<<"*************************************************"<<endl;
cout<<"0退出并销毁二叉树"<<endl;
cout<<"1数据文件创建二叉树"<<endl;
cout<<"2控制台交互输入创建二叉树"<<endl;
cout<<"3先序、中序、后序遍历输出"<<endl;
cout<<"4中序次序输出二叉树中各结点的值及其所对应的层次数"<<endl;
cout<<"5求二叉树的高度"<<endl;
cout<<"6求二叉树的结点数"<<endl;
cout<<"7求二叉树的叶子结点数"<<endl;
cout<<"8求二叉树的度为2的结点数"<<endl;
cout<<"9键盘输入一个元素x,求其父节点、兄弟结点、孩子结点的值"<<endl;
cout<<"10键盘输入一个元素x,求其在树中的层次"<<endl;
cout<<"11将按顺序方式存储在数组中的二叉树转换为二叉链表形式"<<endl;
cout<<"12交换二叉树中每个结点的左右孩子指针的值"<<endl;
cout<<"13复制一棵二叉树T到T1(选做题)"<<endl;
cout<<"14递归输出二叉树从每个叶子结点到根结点的路径(选做题)"<<endl;
cout<<"15对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印(选做题)"<<endl;
cout<<"16对二叉链表表示的二叉树,求2个结点最近的共同祖先(选做题)"<<endl;
cout<<"17求二叉树中一条最长的路径长度(边数),并输出路径上的个结点值(选做题)"<<endl;
cout<<"18非递归输出二叉树从每个叶子结点到根结点的路径(选做题)"<<endl;
cout<<"*************************************************"<<endl;
}
//从文件读取数据
template<class ElementType>
bool BiTree<ElementType>::ReadFileToArray(char fileName[],char strLine[100][3],int & nLen)
{
FILE *pFile; //定义二叉树文件指针
char str[1000]; //存放读取一行文本的字符串
pFile=fopen(fileName,"r");
if(!pFile)
{
cout<<"文件打开失败!"<<endl;
return false;
}
//读取文件第一行,判断二叉树标识BinaryTree是否正确
if(fgets(str,1000,pFile)!=NULL)
{
if(strcmp(str,"BinaryTree\n")!=0)
{
cout<<"打开的文件格式错误!"<<endl;
fclose(pFile);
return false;
}
}
nLen=1;
while(fscanf(pFile,"%c %c %c\n",&strLine[nLen][0],&strLine[nLen][1],&strLine[nLen][2])!=EOF)
{
nLen++;
}
fclose(pFile);
return true;
}
//从文件创建二叉树
template<class ElementType>
bool BiTree<ElementType>::CreatBiTreeFromFile(Node<ElementType> *&pBT,char strLine[100][3],int nLen,int & nRow)
{
if((nRow>=nLen)||(nRow==0))
{
return false; //数据已处理完毕,或者没有数据
}
//根据数组数据递归创建二叉树
pBT=new Node <ElementType> ;
pBT->data=strLine[nRow][0];
pBT->lChild=NULL; //初始化左孩子为空
pBT->rChild=NULL; //初始化右孩子为空
int nRowNext=nRow; //保留本次递归的行号
if(strLine[nRowNext][1]=='1')
{
nRow++; //行号加一
CreatBiTreeFromFile(pBT->lChild,strLine,nLen,nRow); //递归创建左子树
}
if(strLine[nRowNext][2]=='1')
{
nRow++; //行号加一
CreatBiTreeFromFile(pBT->rChild,strLine,nLen,nRow); //递归创建右子树
}
return true;
}
//创建子树函数
template<class ElementType>
void BiTree<ElementType>::createSubTree(Node <ElementType> * p,int k)
{
//q为当前节点
//k=1时为左子树
Node <ElementType> * u;
ElementType x;
cin>>x; //键盘读入节点数据
if(x!='/') //x='/'表示没有左子树
{
u=new Node <ElementType>;
u->data=x;
u->lChild=NULL;
u->rChild=NULL;
if(k==1)
{
p->lChild=u; //新节点为当前根节点q的左子树
}
if(k==2)
{
p->rChild=u; //新节点为当前根节点q的右子树
}
createSubTree(u,1); //递归创建u的左子树
createSubTree(u,2); //递归创建u的右子树
}
}
//创建二叉树函数
template<class ElementType>
void BiTree<ElementType>::createBiTree(Node <ElementType> *&T)
{
Node <ElementType> * p;
ElementType x;
cout<<"请按先序序列依次输入二叉树(‘/’为无子树)"<<endl;
cin>>x;
if(x=='/')
return ; //空树,退出
T=new Node <char>;
T->data=x;
T->lChild=NULL;
T->rChild=NULL;
p=T;
createSubTree(p,1); //创建根节点左子树
createSubTree(p,2); //创建根节点右子树
}
//先序遍历算法
template<class ElementType>
void BiTree<ElementType>::perOrderTraverse(Node <ElementType> * T)
{
if(T)
{
cout<<T->data<<" "; //访问根节点
perOrderTraverse(T->lChild); //递归调用先序遍历左子树rChild
perOrderTraverse(T->rChild); //递归调用先序遍历右子树
}
}
//中序遍历算法
template<class ElementType>
void BiTree<ElementType>::inOrderTraverse(Node <ElementType> * T)
{
if(T)
{
inOrderTraverse(T->lChild); //递归调用先序遍历左子树
cout<<T->data<<" "; //访问根节点
inOrderTraverse(T->rChild); //递归调用先序遍历右子树
}
}
//后序遍历算法
template<class ElementType>
void BiTree<ElementType>::postOrderTraverse(Node <ElementType> * T)
{
if(T)
{
postOrderTraverse(T->lChild); //递归调用先序遍历左子树
postOrderTraverse(T->rChild); //递归调用先序遍历右子树
cout<<T->data<<" "; //访问根节点
}
}
//中序次序输出二叉树中各结点的值及其所对应的层次数
template<class ElementType>
void BiTree<ElementType>::outOrderTraverse(Node <ElementType> * T,int level)
{
if(T)
{
outOrderTraverse(T->lChild,level+1); //递归调用先序遍历左子树
cout<<"("<<T->data<<","<<level<<")"<<endl; //访问根节点,并输出层数
outOrderTraverse(T->rChild,level+1); //递归调用先序遍历右子树
}
}
//求树的高度
template<class ElementType>
int BiTree<ElementType>::BiTreeDepth(Node <ElementType> * T)
{
int m,n;
if(T==NULL)
return 0; //空树,高度为0
else{
m=BiTreeDepth(T->lChild); //求左子树高度(递归)
n=BiTreeDepth(T->rChild); //求右子树高度(递归)
if(m>n)
{
return m+1;
}
else{
return n+1;
}
}
}
//求二叉树的结点数
template<class ElementType>
void BiTree<ElementType>::GetNodeNumber(Node <ElementType> * T,int &nNodeNum)
{
if(T!=NULL)
{
GetNodeNumber(T->lChild,nNodeNum);
nNodeNum++;
GetNodeNumber(T->rChild,nNodeNum);
}
}
//求二叉树的叶子结点数。
template<class ElementType>
void BiTree<ElementType>::leafNodeNum(Node <ElementType> *T,int &nNodeNum)
{
if(T!=NULL)
{
leafNodeNum(T->lChild,nNodeNum);
if(T->lChild==NULL&&T->rChild==NULL)
{
nNodeNum++;
}
leafNodeNum(T->rChild,nNodeNum);
}
}
//求二叉树的度为2的结点数
template<class ElementType>
void BiTree<ElementType>::TwoBranchNodeNum(Node <ElementType> *T,int &nNodeNum)
{
if(T!=NULL)
{
TwoBranchNodeNum(T->lChild,nNodeNum);
if(T->lChild!=NULL&&T->rChild!=NULL)
{
nNodeNum++;
}
TwoBranchNodeNum(T->rChild,nNodeNum);
}
}
//键盘输入一个元素x,求其父节点、兄弟结点、子结点的值,不存在时给出相应提示信息。对兄弟结点和孩子结点,存在时要明确指出是左兄弟、左孩子、右兄弟或右孩子
template<class ElementType>
void BiTree<ElementType>::GetFatherBrotherChildNode(Node <ElementType> *T,ElementType x)
{
if(T)
{
if(T->lChild!=NULL)
{
if(T->lChild->data==x)
{
cout<<"父节点的值为:"<<T->data<<endl; //输出父节点的值
if(T->rChild==NULL)
{
cout<<"右兄弟不存在!"<<endl; //判断右兄弟是否存在,存在输出其值
}
else{
cout<<"右兄第为:"<<T->rChild->data<<endl;
}
if(T->lChild->lChild==NULL)
{
cout<<"左孩子不存在!"<<endl;
}
else{
cout<<"左孩子为:"<<T->lChild->lChild->data<<endl;
}
if(T->lChild->rChild==NULL)
{
cout<<"右孩子不存在!"<<endl;
}
else{
cout<<"右孩子为:"<<T->lChild->lChild->data<<endl;
}
}
}
if(T->rChild!=NULL)
{
if(T->rChild->data==x)
{
cout<<"父节点的值为:"<<T->data<<endl; //输出父节点的值
if(T->lChild==NULL)
{
cout<<"左兄弟不存在!"<<endl; //判断左兄弟是否存在,存在输出其值
}
else{
cout<<"左兄第为:"<<T->lChild->data<<endl;
}
if(T->rChild->lChild==NULL)
{
cout<<"左孩子不存在!"<<endl;
}
else{
cout<<"左孩子为:"<<T->rChild->lChild->data<<endl;
}
if(T->rChild->rChild==NULL)
{
cout<<"右孩子不存在!"<<endl;
}
else{
cout<<"右孩子为:"<<T->rChild->rChild->data<<endl;
}
}
}
GetFatherBrotherChildNode(T->lChild,x);
GetFatherBrotherChildNode(T->rChild,x);
}
}
//键盘输入一个元素x,求其在树中的层次。不存在时给出相应提示信息
template<class ElementType>
void BiTree<ElementType>::GetNodeLevel(Node <ElementType> * T,ElementType x,int level,int & flag)
{
if(T!=NULL)
{
GetNodeLevel(T->lChild,x,level+1,flag);
if(T->data==x)
{
cout<<"该节点层次为:"<<level<<endl;
flag=1;
}
GetNodeLevel(T->rChild,x,level+1,flag);
}
}
//将按顺序方式存储在数组中的二叉树转换为二叉链表形式。(数组中要扩展为完全二叉树)
template<class ElementType>
void BiTree<ElementType>::ArrayToBiTree(Node <ElementType> *&T,ElementType A[],int i,int num)
{
if(i<=num&&A[i])
{
T=new Node <ElementType>;
if(A[i]!='0')
T->data=A[i];
T->lChild=NULL;
T->rChild=NULL;
ArrayToBiTree(T->lChild,A,2*i,num);
ArrayToBiTree(T->rChild,A,2*i+1,num);
}
}
//交换二叉树中每个结点的左右孩子指针的值
template<class ElementType>
void BiTree<ElementType>::ExchangeTree(Node <ElementType> *&T)
{
Node <ElementType> * temp;
if(T!=NULL)
{
temp=T->lChild;
T->lChild=T->rChild;
T->rChild=temp;
ExchangeTree(T->lChild);
ExchangeTree(T->rChild);
}
}
//二叉树转数组
template<class ElementType>
void BiTree<ElementType>::BiTreeToArray(Node <ElementType> *T,ElementType A[],int i,int &count)
{
if(T!=NULL)
{
A[i]=T->data;
if(i>count)
count=i;
BiTreeToArray(T->lChild,A,2*i,count);
BiTreeToArray(T->rChild,A,2*i+1,count);
}
}
//输出二叉树从每个叶子结点到根结点的路径
template<class ElementType>
void BiTree<ElementType>::PrintRoute(Node <ElementType> *T,ElementType path[],int pathLen)
{
int i;
if(T!=NULL)
{
if(T->lChild==NULL&&T->rChild==NULL)
{
cout<<T->data<<"到根节点的路径为:"<<T->data<<" ";
for(i=pathLen-1;i>=0;i--)
{
cout<<path[i]<<" ";
}
cout<<endl;
}
else{
path[pathLen]=T->data;
pathLen++;
PrintRoute(T->lChild,path,pathLen);
PrintRoute(T->rChild,path,pathLen);
pathLen--;
}
}
}
//对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印
template<class ElementType>
void BiTree<ElementType>::LevelTraverse(Node <ElementType> *T,ElementType B[],int num)
{
int n,i,j,t,q,s,p,m=0,k=0;
n=(int)((log(num)/log(2))+1);
p=n;
for(i=0;i<n;i++)
{
k=pow(2,m)+k;
t=pow(2,m);
j=pow(2,p-1)-1;
q=pow(2,p)-1;
s=q;
for(j;j>0;j--)
{
cout<<" ";
}
for(t;t<=k;t++)
{
if(B[t]==0)
{
cout<<"*";
for(q;q>0;q--)
cout<<" ";
q=s;
}
else{
cout<<B[t];
for(q;q>0;q--)
cout<<" ";
q=s;
}
}
m++;
p--;
j=n-i-1;
cout<<endl;
}
}
//遍历查找节点x,并把路径保存在栈s中
template<class ElementType>
void BiTree<ElementType>::SearchBiTree(Node <ElementType> *T,Stack<Node <ElementType> *> &s,ElementType x)
{
Node <ElementType> *p;
int tag[100];
p=T;
while(p||!s.empty())
{
if(p)
{
s.push(p);
tag[s.getLen()-1]=0;
if(p->data==x)
{
break;
}
else{
p=p->lChild;
}
}
else{
p=s.top();
if(tag[s.getLen()-1]==0)
{
tag[s.getLen()-1]=1;
p=p->rChild;
}
else{
s.pop(p);
p=NULL;
}
}
}
}
//求二叉树中一条最长的路径长度(边数),并输出路径上的结点值
template<class ElementType>
void BiTree<ElementType>::PrintMaxLenPath(Node <ElementType> *T,int MaxLen)
{
Node <ElementType> *p;
Stack<Node <ElementType> *> s;
int t=MaxLen;
int tag[100];
p=T;
while(p||!s.empty())
{
if(p)
{
s.push(p);
tag[s.getLen()-1]=0;
if(s.getLen()==MaxLen)
{
cout<<"最长路径长度为:"<<MaxLen<<endl;
cout<<"最长路径为:";
while(MaxLen)
{
cout<<s.getData(MaxLen-1)->data<<" ";
MaxLen--;
}
cout<<endl;
MaxLen=t;
p=p->lChild;
}
else{
p=p->lChild;
}
}
else{
p=s.top();
if(tag[s.getLen()-1]==0)
{
tag[s.getLen()-1]=1;
p=p->rChild;
}
else{
s.pop(p);
p=NULL;
}
}
}
}
//非递归输出二叉树从每个叶子结点到根结点的路径(选做题)
template<class ElementType>
void BiTree<ElementType>::PrintAllPath(Node <ElementType> *T)
{
Node <ElementType> *p;
Stack<Node <ElementType> *> s;
int t;
int tag[100];
p=T;
while(p||!s.empty())
{
if(p)
{
s.push(p);
tag[s.getLen()-1]=0;
t=s.getLen();
if(p->lChild==NULL&&p->rChild==NULL)
{
cout<<p->data<<"到根节点路径为:";
while(t)
{
cout<<s.getData(t-1)->data<<" ";
t--;
}
cout<<endl;
p=p->lChild;
}
else{
p=p->lChild;
}
}
else{
p=s.top();
if(tag[s.getLen()-1]==0)
{
tag[s.getLen()-1]=1;
p=p->rChild;
}
else{
s.pop(p);
p=NULL;
}
}
}
}
#endif // _BITREE_H_
#include <iostream>
#include <Cstdlib>
#include "BiTree.h"
#include "seqStack.h"
using namespace std;
int main()
{
int x;
Node <char> * root=NULL; //定义根节点root
Node <char> *c,d;
BiTree <char> T(root); //初始化
Node <char> * root1=NULL; //定义根节点root1
BiTree <char> T1(root1); //初始化
char fileName[100]; //保存文件名
char strLine[100][3]; //保存二叉树文件数据
int nLen; //保存节点个数
int nRow=1; //当前行数
int level=1; //表示二叉树的层次
int nNodeNum=0; //节点总数
int leafNodeNum=0; //保存叶子节点数,初始化为0
int TwoBranchNodeNum=0; //保存度为2的节点,初始化为0
char y,z; //保存输入元素
int flag=0; //标志位,初始化为0
char A[100]={0}; //顺序二叉树
char B[100]={0};
int i=1; //数组下标,初始化为1
int num=0; //第num个有效下标,初始化为0
int count=1; //记录树中节点个数
int pathLen=0; //存放路径长度
int nLayer=1; //深度为一层
Stack<Node <char> *> s1,s2; //定义两个栈
int maxLen;
BiTree <char> ::menu(); //二叉树操作菜单
cout<<"请输入执行序号:";
cin>>x;
while(x!=0)
{
switch(x)
{ //数据文件创建二叉树
case 1:
if(root!=NULL)
{
T.destory(root);
}
cout<<"请输入打开的文件名:";
cin>>fileName;
if(T.ReadFileToArray(fileName,strLine,nLen))
{
if(T.CreatBiTreeFromFile(root,strLine,nLen,nRow))
{
cout<<"数据处理完毕!"<<endl;
}
}
break;
//控制台交互输入创建二叉树
case 2:
if(root!=NULL)
{
T.destory(root);
}
T.createBiTree(root);
break;
//3先序、中序、后序遍历输出
case 3:
cout<<"先序序列为:";
T.perOrderTraverse(root);
cout<<endl;
cout<<"中序序列为:";
T.inOrderTraverse(root);
cout<<endl;
cout<<"后序序列为:";
T.postOrderTraverse(root);
cout<<endl;
break;
//4中序次序输出二叉树中各结点的值及其所对应的层次数
case 4:
T.outOrderTraverse(root,level);
break;
//5求二叉树的高度
case 5:
cout<<"此树高度为:"<<T.BiTreeDepth(root)<<endl;
break;
//6求二叉树的结点数
case 6:
T.GetNodeNumber(root,nNodeNum);
cout<<"共有"<<nNodeNum<<"个节点"<<endl;
break;
//7求二叉树的叶子结点数
case 7:
T.leafNodeNum(root,leafNodeNum);
cout<<"共有"<<leafNodeNum<<"个叶子节点"<<endl;
break;
//8求二叉树的度为2的结点数
case 8:
T.TwoBranchNodeNum(root,TwoBranchNodeNum);
cout<<"共有"<<TwoBranchNodeNum<<"个度为2的节点"<<endl;
break;
//9键盘输入一个元素x,求其父节点、兄弟结点、孩子结点的值
case 9:
cout<<"请输入要查询x的值:";
cin>>y;
T.GetFatherBrotherChildNode(root,y);
break;
//10键盘输入一个元素x,求其在树中的层次
case 10:
cout<<"请输入要查询x的值:";
cin>>y;
T.GetNodeLevel(root,y,level,flag);
break;
//11将按顺序方式存储在数组中的二叉树转换为二叉链表形式
case 11:
if(root!=NULL)
{
T.destory(root);
}
cout<<"请依次输入字符(输入字符\\结束):"<<endl;
for(int t=1;t<100;t++)
{
cin>>y;
if(y=='\\') //注意转义字符的使用
break;
A[t]=y;
num++;
}
T.ArrayToBiTree(root,A,i,num);
break;
//12交换二叉树中每个结点的左右孩子指针的值
case 12:
T.ExchangeTree(root);
cout<<"交换完成!";
break;
//13复制一棵二叉树T到T1(选做题)
case 13:
// T.GetNodeNumber(root,nNodeNum);
T.BiTreeToArray(root,A,i,count);
T1.ArrayToBiTree(root1,A,i,count);
cout<<"复制完成!"<<endl;
cout<<"先序序列为:";
T1.perOrderTraverse(root1);
cout<<endl;
cout<<"中序序列为:";
T1.inOrderTraverse(root1);
cout<<endl;
cout<<"后序序列为:";
T1.postOrderTraverse(root1);
cout<<endl;
break;
case 14:
T.PrintRoute(root,A,pathLen);
break;
case 15:
count=i=1;
T.BiTreeToArray(root,B,i,count);
T.LevelTraverse(root,B,count);
count=i=1;
break;
case 16:
cout<<"请输入树中节点的元素值:";
cin>>y;
cout<<"请输入树中另一个节点的元素值:";
cin>>z;
T.SearchBiTree(root,s1,y);
T.SearchBiTree(root,s2,z);
while((s1.top()!=s2.top())||s1.getLen()!=s2.getLen())
{
if(s1.getLen()>s2.getLen())
{
s1.pop(c);
}
else if(s1.getLen()<s2.getLen())
{
s2.pop(c);
}
else{
if(s1.top()==s2.top())
{
break;
}
else{
s1.pop(c);
s2.pop(c);
}
}
}
if(s1.top()->data==s2.top()->data&&s1.top()->data==y)
{
s1.pop(c);
cout<<"两个节点的共同祖先为:"<<s1.top()->data<<endl;
}
else if(s1.top()->data==s2.top()->data&&s1.top()->data==z)
{
s1.pop(c);
cout<<"两个节点的共同祖先为:"<<s1.top()->data<<endl;
}
else{
cout<<"两个节点的共同祖先为:"<<s1.top()->data<<endl;
}
break;
case 17:
maxLen=T.BiTreeDepth(root);
T.PrintMaxLenPath(root,maxLen);
break;
case 18:
T.PrintAllPath(root);
break;
}
system("PAUSE");
system("CLS");
BiTree <char> ::menu();
cout<<"请输入执行序号:";
cin>>x;
}
//这里需要添加销毁二叉树的相关操作
if(root!=NULL)
T.destory(root);
T1.destory(root1);
return 0;
}