实验五 二叉树操作
一、 要求完成时间
实验开始后的第六周之前完成
二、 实验目的
掌握二叉树的基本概念,二叉树的存储结构使用链表。
三、 实验内容
1、 输入一个完全二叉树的层次遍历字符串,创建这个二叉树,输出这个二叉树的前序遍历字符串、中序遍历字符串、后序遍历字符串、结点数目、二叉树高度(上述每一个结果独立一行显示)。
2、 输入二叉树前序序列和中序序列(各元素各不相同),创建这个二叉树,输出该二叉树的后序序列、层次遍历。
四、 测试用例及答案
测试如下所有用例及答案,且确保运行后出现完全一样的输出,
(操作系统提示“请按任意键继续….”等,可以不一样。)
分析:
1.前序、中序、后序、层次遍历以及求节点和树高书上有相应的代码,唯一需要修改的是,实验输出要求用逗号分隔,所以对于不同方式的遍历需要用不同的方法判断并输出逗号。统一的方法是先将元素放在队列里再输出,这样就能保证正确。
2.第二题通过前序和中序确定二叉树,我采用的是递归创建根节点,根节点的左子树以及右子树。生成左右子树的前序和中序,直到为空结束。
以下是代码,有点略多,仅供参考,希望你写出更好的方法!
代码:
#include<iostream>
#include<string>
using namespace std;
//处理数BadInput的报错
class BadInput{
public:
BadInput(){
cout<<"BadInput!"<<endl;
}
};
//BinaryTreeNode
template <class T>class BinaryTreeNode;
template <class T>class BinaryTree;
template <class T>void Visit(BinaryTreeNode<T> *);
template <class T>void InOrder(BinaryTreeNode<T> *,bool isroot);
template <class T>void PreOrder(BinaryTreeNode<T> *,bool isroot);
template <class T>void PostOrder(BinaryTreeNode<T> *,bool isroot);
template <class T>void LevelOrder(BinaryTreeNode<T> *,bool isroot);
template <class T>void Confirm_By_Pre_And_In(BinaryTreeNode<T> *,char[],char[],int);
template <class T>
class BinaryTreeNode{
friend BinaryTree<T>;//友元类
friend void Visit<T>(BinaryTreeNode<T> *);//访问节点元素
friend void InOrder<T>(BinaryTreeNode<T> *,bool isroot);//中序遍历(左->根->右)
friend void PreOrder<T>(BinaryTreeNode<T> *,bool isroot);//前序遍历(根->左->右)
friend void PostOrder<T>(BinaryTreeNode<T> *,bool isroot);//后序遍历(左->右->根)
friend void LevelOrder<T>(BinaryTreeNode<T> *,bool isroot);//逐层遍历
friend void Confirm_By_Pre_And_In<T>(BinaryTreeNode<T> *,char[],char[],int);//通过前序和中序确定二叉树
public:
BinaryTreeNode(){
LeftChild = RightChild = 0;
}
BinaryTreeNode(const T& e){
data = e;
LeftChild = RightChild = 0;
}
BinaryTreeNode(const T& e,BinaryTreeNode *l,BinaryTreeNode *r){
data = e;
LeftChild = l;
RightChild = r;
}
private:
T data;
BinaryTreeNode<T> *LeftChild,*RightChild;//左子树,右子树
};
//访问节点元素
template<class T>
void Visit(BinaryTreeNode<T> *t){
cout<<t->data;
}
//前序遍历(根->左->右)
template<class T>
void PreOrder(BinaryTreeNode<T> *t,bool isroot){
if(t){
if(!isroot) cout<<",";
Visit(t);
PreOrder(t->LeftChild,false);
PreOrder(t->RightChild,false);
}
}
//中序遍历(左->根->右)
template<class T>
void InOrder(BinaryTreeNode<T> *t,bool isroot){
if(t){
InOrder(t->LeftChild,false);
if(!isroot) cout<<",";
Visit(t);
InOrder(t->RightChild,false);
}
}
//后序遍历(左->右->根)
template<class T>
void PostOrder(BinaryTreeNode<T> *t,bool isroot){
if(t){
PostOrder(t->LeftChild,false);
PostOrder(t->RightChild,false);
Visit(t);
if(!isroot) cout<<",";
}
}
//逐层遍历
template<class T>
void LevelOrder(BinaryTreeNode<T> *t,bool isroot){
if(t){
if(isroot)
Visit(t);
if(t->LeftChild){
cout<<",";
Visit(t->LeftChild);
}
if(t->RightChild){
cout<<",";
Visit(t->RightChild);
}
LevelOrder(t->LeftChild,false);
LevelOrder(t->RightChild,false);
}
}
//通过前序和中序确定二叉树
template<class T>
void Confirm_By_Pre_And_In(BinaryTreeNode<T> *t,char PreOrder_data[],char InOrder_data[],int n){
if(n > 0){
t->data = PreOrder_data[0];
int index = 0;
for(int i = 0;i < n;i++){
if(InOrder_data[i] == t->data){
index = i;
break;
}
}
if(index > 0){
//左子的中序遍历
char subLeftInOrder_data[index];
for(int i = 0;i < index;i++){
subLeftInOrder_data[i] = InOrder_data[i];
}
//左子的前序遍历
char subLeftPreOrder_data[index];
for(int i = 1,x = 0;i < n;i++){
for(int j = 0;j < index;j++){
if(PreOrder_data[i] == subLeftInOrder_data[j]){
subLeftPreOrder_data[x++] = PreOrder_data[i];
break;
}
}
}
//构建左子
BinaryTreeNode<char>* left = new BinaryTreeNode<char> (subLeftPreOrder_data[0]);
t->LeftChild = left;
Confirm_By_Pre_And_In(t->LeftChild,subLeftPreOrder_data,subLeftInOrder_data,index);
}
if(n-index-1 > 0){
//右子的中序遍历
char subRightInOrder_data[n-index-1];
for(int i = index+1;i < n;i++){
subRightInOrder_data[i-index-1] = InOrder_data[i];
}
//右子的前序遍历
char subRightPreOrder_data[n-index-1];
for(int i = 1,x = 0;i < n;i++){
for(int j = 0;j < n-index-1;j++){
if(PreOrder_data[i] == subRightInOrder_data[j]){
subRightPreOrder_data[x++] = PreOrder_data[i];
break;
}
}
}
//构建右子
BinaryTreeNode<char>* Right = new BinaryTreeNode<char>(subRightPreOrder_data[0]);
t->RightChild = Right;
Confirm_By_Pre_And_In(t->RightChild,subRightPreOrder_data,subRightInOrder_data,n-index-1);
}
}
}
int _count = 0;
int index = 0;
template<class T>
class BinaryTree{
public:
BinaryTree(){root = 0;};
~BinaryTree(){};
bool IsEmpty() const{
return ((root)?false:true);
}
bool Root(T& x) const;
void MakeTree(const T& element,BinaryTree<T>& left,BinaryTree<T>& right);
void BreakTree(T& element,BinaryTree<T>& left,BinaryTree<T>& right);
int Height()const{return Height(root);};//计算二叉树的高度
int Size();//统计节点数
void Delete(){PostOrder(Free,root);root = 0;}
void PreOrder(void(*Visit)(BinaryTree<T> *u)){
PreOrder(Visit,root);
}
void PreOutput(){PreOrder(Output,root,true);};
void InOrder(void(*Visit)(BinaryTree<T> *u)){
InOrder(Visit,root);
}
void InOutput(){static int i = 0;InOrder(Output2,root,i);};
void PostOrder(void(*Visit)(BinaryTree<T> *u)){
PostOrder(Visit,root);
}
void PostOutput(){PostOrder(Output,root,true);};
private:
BinaryTreeNode<T> *root;//根节点指针
int Height(BinaryTreeNode<T> *t) const;
void PreOrder(void(*Visit)(BinaryTreeNode<T> *u),BinaryTreeNode<T> *t);
void PreOrder(void(*Visit)(BinaryTreeNode<T> *u),BinaryTreeNode<T> *t,bool isroot);
void InOrder(void(*Visit)(BinaryTreeNode<T> *u),BinaryTreeNode<T> *t);
void InOrder(void(*Visit)(BinaryTreeNode<T> *u,int i),BinaryTreeNode<T> *t,int i);
void PostOrder(void(*Visit)(BinaryTreeNode<T> *u),BinaryTreeNode<T> *t,bool isroot);
static void Output(BinaryTreeNode<T> *t){cout<<t->data;};
static void Output2(BinaryTreeNode<T> *t,int i){
if(i != 0)cout<<",";
cout<<t->data;};
static void Add1(BinaryTreeNode<T> *t){_count++;};
static void Free(BinaryTreeNode<T> *t){delete t;};
};
template<class T>
bool BinaryTree<T>::Root(T& x) const{
if(root){
x = root->data;
return true;
}else
return false;
}
template<class T>
void BinaryTree<T>::MakeTree(const T& element,BinaryTree<T>& left,BinaryTree<T>& right){
root = new BinaryTreeNode<T>(element,left.root,right.root);
left.root = right.root = 0;
}
template<class T>
void BinaryTree<T>::BreakTree(T& element,BinaryTree<T>& left,BinaryTree<T>& right){
if(!root)
throw BadInput();
//分解树
element = root->data;
left.root = root->LeftChild;
right.root = root->RightChild;
delete root;
root = 0;
}
template<class T>
int BinaryTree<T>::Height(BinaryTreeNode<T> *t) const{
if(!t) return 0;//空树
int hl = Height(t->LeftChild);//左树的高度
int hr = Height(t->RightChild);//右树的高度
if(hl > hr) return ++hl;
else return ++hr;
}
template<class T>
int BinaryTree<T>::Size(){
_count = 0;
PreOrder(Add1,root);
return _count;
}
template<class T>
void BinaryTree<T>::PreOrder(void(*Visit)(BinaryTreeNode<T> *u),BinaryTreeNode<T> *t){
if(t){
Visit(t);
PreOrder(Visit,t->LeftChild);
PreOrder(Visit,t->RightChild);
}
}
template<class T>
void BinaryTree<T>::PreOrder(void(*Visit)(BinaryTreeNode<T> *u),BinaryTreeNode<T> *t,bool isroot){
if(t){
if(!isroot)cout<<",";
Visit(t);
PreOrder(Visit,t->LeftChild,false);
PreOrder(Visit,t->RightChild,false);
}
}
template<class T>
void BinaryTree<T>::InOrder(void(*Visit)(BinaryTreeNode<T> *u,int i),BinaryTreeNode<T> *t,int i){
if(t){
InOrder(Visit,t->LeftChild,i);
if(t->LeftChild)i++;
Visit(t,i);
InOrder(Visit,t->RightChild,i);
}
}
template<class T>
void BinaryTree<T>::PostOrder(void(*Visit)(BinaryTreeNode<T> *u),BinaryTreeNode<T> *t,bool isroot){
if(t){
PostOrder(Visit,t->LeftChild,false);
PostOrder(Visit,t->RightChild,false);
Visit(t);
if(!isroot)cout<<",";
}
}
int main(){
cout<<"Input1"<<endl;
string input;
cin>>input;
int length = input.length();
BinaryTree<char> empty;
BinaryTree<char> *btree = new BinaryTree<char>[length];
for(int i = length-1;i >= 0;i--){
btree[i].MakeTree(input[i],(2*i+1 < length?btree[2*i+1]:empty),(2*i+2 < length?btree[2*i+2]:empty));
}
cout<<"Output1"<<endl;
btree[0].PreOutput();cout<<endl;
btree[0].InOutput();cout<<endl;
btree[0].PostOutput();cout<<endl;
cout<<btree[0].Size()<<endl;
cout<<btree[0].Height()<<endl;
delete btree;
cout<<"Input2"<<endl;
string input1,input2;
cin>>input1>>input2;
int length1 = input1.length();
char PreOrder_data[length1];
char InOrder_data[length1];
for(int i = 0;i < length1;i++){
PreOrder_data[i] = input1[i];
InOrder_data[i] = input2[i];
}
BinaryTreeNode<char> tree(0);
Confirm_By_Pre_And_In(&tree,PreOrder_data,InOrder_data,length1);
cout<<"Output2"<<endl;
PostOrder(&tree,true);cout<<endl;
LevelOrder(&tree,true);cout<<endl;
cout<<"End";
return 0;
}
运行截图:
ps:本人开通了个人的微信公众号,希望大家能关注一下,
我会将资源、文章优先推送到公众号上。
推送自己的一些学习笔记,实验源代码等,
欢迎大家互相交流学习。