山东大学 数据结构 实验5 二叉树操作

实验五  二叉树操作

一、 要求完成时间

实验开始后的第六周之前完成

二、 实验目的

掌握二叉树的基本概念,二叉树的存储结构使用链表。

三、 实验内容

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:本人开通了个人的微信公众号,希望大家能关注一下,

我会将资源、文章优先推送到公众号上。

推送自己的一些学习笔记,实验源代码等,

欢迎大家互相交流学习。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值