数据结构-二叉树-树的构建+7种遍历方式+求度为1、2以及叶子结点的个数+树中最值!!

以二叉链表作为存储结构编写程序,实现如下功能:
将近400行代码,觉得挺好的给个关注给个赞吧!谢谢
1、根据输入的数据建立一个二叉树;
2、分别采用前序、中序、后序的遍历方式显示输出二叉树的遍历结果
3、采用非递归的编程方法,分别统计二叉树的节点个数、度为1、度为2和叶子节点的个数,以及数据值的最大值和最小值。
4.7种递归方式:递归前序、递归中序、递归后序、层序
、非递归前序、非递归后序、非递归中序
代码如下(内含注释)!!
由于非递归遍历以及层次遍历需要栈和队列、因此其中还包含栈、队列的构建!!

输入:PBC##DE###GF#I##H##
预期输出:
经前序遍历后的结果为:P B C D E G F I H
经中序遍历后的结果为:C B E D P F I G H
经后序遍历后的结果为:C E D B I F H G P
经层序遍历后的结果为:P B G C D F H E I
经非递归前序遍历后的结果为:P B C D E G F I H
经非递归中序遍历后的结果为:C B E D P F I G H
经非递归后序遍历后的结果为:C E D B I F H G P
该二叉树中含有9个结点
该二叉树中度为2的结点有3个
该二叉树中度为1的结点有2个
该二叉树中叶子结点有4个
该二叉树中最大数据值为:P
该二叉树中最小数据值为:B

#include <iostream>
using namespace std;
//============栈结构================
template <class T>
struct Node{
	//成员变量 
	T data;
	Node *next;
	//构造函数
	Node(T x) : data(x), next(NULL) {}
	Node(){}
};
//模板类
template <class T>
class Stack{
	//私有成员变量
private:
	Node<T> *head;
	//栈的大小
	int sizeOfStack;
public:
	//构造函数
	Stack() : head(NULL), sizeOfStack(0) {}//参数总表
	//成员方法
	//求栈的大小
	int size();
	//判断是否为空
	bool isEmpty();
	//入栈
	void push(T x);
	//出栈
	void pop();
	//求栈顶元素
	T top();
};
//栈是否为空
template <class T>
bool Stack<T>::isEmpty(){
	return sizeOfStack == 0;
}
//压栈
template <class T>
void Stack<T>::push(T x){
	//新建一个结点
	Node<T> *node = new Node<T>(x);
	node->next = head;
	head = node;
	sizeOfStack++;
}
//出栈
template <class T>
void Stack<T>::pop(){
	if (isEmpty()) return;//若无元素,则退出当前方法
	Node<T> *p = head;
	head = head->next;
	delete p;
	sizeOfStack--;
}
//获取栈顶元素
template <class T>
T Stack<T>::top(){
	
	return head->data;
}
//==============队列==================

//模板类
template <class T>
class Quene{
private:
	//头指针、尾指针 
	Node<T> *front;
	Node<T> *rear;
	//队列大小
	int sizeOfQuene;
public:
	//构造函数L:
	Quene(){
		front = new Node<T>();
		rear = new Node<T>();
		front->next = rear;
		rear->next = NULL;
		sizeOfQuene = 0;
	}
	//成员方法 
	//初始化 
	//	void initQuene();
	//入队
	void enQuene(T data);
	//出队
	T ouQuene();
	//是否为空
	bool isEmpty();
};

//队列是否为空
template <class T>
bool Quene<T>::isEmpty(){
	return sizeOfQuene == 0;
}
//入队
template <class T>
void Quene<T>::enQuene(T x){
	Node<T> *node = new Node<T>(x);
	Node<T> *p = front;
	while (p->next != rear){
		p = p->next;
	}
	p->next = node;
	node->next = rear;
	sizeOfQuene++;
}
//出队
template <class T>
T Quene<T>::ouQuene(){
	Node<T> *p = front->next;
	front->next = front->next->next;
	sizeOfQuene--;
	return p->data;
}
//==============队列==================
//==============二叉树================
//结点类型
class BiNode{
public:
	//数据域
	char data;
	//左右孩子指针
	BiNode *left_Child;
	BiNode *right_Child;
};
//二叉树类
class BiTree{
	//用根结点表示一棵二叉树
public:
	BiNode *root;
	//构造函数
	BiTree(){
		root = createTree(root);
	}
	//创建树
	BiNode* createTree(BiNode *bt);
	//递归前序遍历树
	void preOrderTraverse(BiNode *bt);
	//递归中序遍历树
	void inOrderTraverse(BiNode *bt);
	//递归后序遍历树
	void postOrderTraverse(BiNode* bt);
	//递归层次遍历树
	void leverOrderTravrse(BiNode* bt);

	//非递归前序遍历
	void unDiGuiPreOrderTraverse(BiNode* b, int &count, int &number, int &amount,char &max, char &min);//引用传递,count是指结点数, 
	//非递归中序遍历
	void unDiGuiInOrderTraverse(BiNode* bt);
	//非递归后序遍历
	void unDiGuiPostOrderTraverse(BiNode* bt);
	//非递归统计结点个数
};
//将指针和入栈次数标记temp封装成一个结构体
struct Flag{
	BiNode* ptr;
	int temp;
};
//建树
BiNode* BiTree::createTree(BiNode *bt){
	char ch;
	cin >> ch;
	if (ch == '#')
		bt = NULL;
	else{
		bt = new BiNode;
		bt->data = ch;
		bt->left_Child = createTree(bt->left_Child);
		bt->right_Child = createTree(bt->right_Child);
	}
	return bt;
}
//递归前序遍历树
void BiTree::preOrderTraverse(BiNode* bt){

	if (bt)
	{
		cout << bt->data << " ";
		preOrderTraverse(bt->left_Child);
		preOrderTraverse(bt->right_Child);
	}
	else{
		return;
	}
}
//递归中序遍历树
void BiTree::inOrderTraverse(BiNode* bt){

	if (bt){
		inOrderTraverse(bt->left_Child);
		cout << bt->data << " ";
		inOrderTraverse(bt->right_Child);
	}
	else{
		return;
	}
}
//递归后序遍历树
void BiTree::postOrderTraverse(BiNode* bt){

	if (bt){
		postOrderTraverse(bt->left_Child);
		postOrderTraverse(bt->right_Child);
		cout << bt->data << " ";
	}
	else{
		return;
	}
}
//层次遍历树
void BiTree::leverOrderTravrse(BiNode* bt){
	//设置队列
	Quene<BiNode*> quene;
	BiNode* p;
	if (bt == NULL) return;
	quene.enQuene(bt);//根先入队
	while (!quene.isEmpty()){
		//出队
		p = quene.ouQuene();
		//访问结点
		cout << p->data<<" ";
		//左孩子入队
		if (p->left_Child != NULL){
			quene.enQuene(p->left_Child);
		}
		if (p->right_Child != NULL){
			quene.enQuene(p->right_Child);
		}
	}

}
//非递归前序遍历
void BiTree::unDiGuiPreOrderTraverse(BiNode* bt, int &count , int &number,int &amount,char &max,char &min){
	//创建一个指针栈
	Stack<BiNode*> s;
	BiNode *p = bt;
	while (p != NULL || !s.isEmpty()){//当p为空且栈也为空时才退出循环
		while (p != NULL){
			//访问根结点

			cout << p->data << " ";
			//最大值
			if (max < p->data){
				max = p->data;
			}
			//最小值
			if (min>p->data){
				min = p->data;
			}
			//节点数
			count++;
			//度为2结点数
			if (p->left_Child&&p->right_Child){
				number++;
			}
			//度为1结点数
			else if (p->left_Child || p->right_Child){
				amount++;
			}
			//将p指向的结点入栈
			s.push(p);
			//遍历左子树
			p = p->left_Child;
		}
		//栈不为空
		if (!s.isEmpty()){
			//根结点出栈
			p = s.top();
			s.pop();
			//遍历右子树
			p = p->right_Child;
		}
	}
}

//非递归中序遍历(与前序十分类似)
void BiTree::unDiGuiInOrderTraverse(BiNode* bt){
	//创建一个指针栈
	Stack<BiNode*> s;
	BiNode *p = bt;
	while (p != NULL || !s.isEmpty()){//当p为空且栈也为空时才退出循环
		while (p != NULL){
			//将p指向的结点入栈
			s.push(p);
			//遍历左子树
			p = p->left_Child;
		}
		//栈不为空
		if (!s.isEmpty()){
			//根结点出栈
			p = s.top();
			//访问根结点
			cout << p->data << " ";
			s.pop();
			//遍历右子树
			p = p->right_Child;
		}
	}
}
//非递归后序遍历(在后序遍历中结点要入两次栈,出两次栈,要加以区分将temp标记和指针封装成一个结构体)
void BiTree::unDiGuiPostOrderTraverse(BiNode* bt){
	//创建一个存储Flag的栈
	Stack<Flag> s;
	Flag flag;
	BiNode *p = bt;
	//当p为空且栈也为空时才退出循环
	while (p != NULL || !s.isEmpty()){
		if (p != NULL){
			flag.ptr = p;
			flag.temp = 1;//标记为1表示第一次入栈
			//将flag压入栈
			s.push(flag);
			//访问左孩子
			p = p->left_Child;
		}
		else{
			//出栈
			flag = s.top();
			s.pop();
			//将p指向当前需要处理的结点
			p = flag.ptr;
			//判断入栈次数,若为1,则表明只访问过左子树,还需继续访问右子树
			if (flag.temp == 1){
				//将temp改为2,即指将要进行第二系入栈
				flag.temp = 2;
				s.push(flag);
				//访问右孩子
				p = p->right_Child;
			}
			//若temp=2则表示左右子树均已被访问
			else{
				//输出结点数据域
				cout << p->data << " ";
				//令p为空,以保证下一次循环时会出栈
				p = NULL;
			}
		}
	}
}

//主函数
int main(){
	//PBC##DE###GF#I##H##
	//创建一棵树
	int count = 0;
	int number = 0;
	int amount = 0;
	char max = 'A';
	char min = 'Z';
	BiTree *tree = new BiTree();
	cout << "经前序遍历后的结果为:";
	tree->preOrderTraverse(tree->root);
	cout << "\n";
	cout << "经中序遍历后的结果为:";
	tree->inOrderTraverse(tree->root);
	cout << "\n";
	cout << "经后序遍历后的结果为:";
	tree->postOrderTraverse(tree->root);
	cout << "\n";
	cout << "经层序遍历后的结果为:";
	tree->leverOrderTravrse(tree->root);
	cout << "\n";
	cout << "经非递归前序遍历后的结果为:";
	tree->unDiGuiPreOrderTraverse(tree->root, count,number,amount,max,min);
	cout << "\n";
	cout << "经非递归中序遍历后的结果为:";
	tree->unDiGuiInOrderTraverse(tree->root);
	cout << "\n";
	cout << "经非递归后序遍历后的结果为:";
	tree->unDiGuiPostOrderTraverse(tree->root);
	cout << "\n";
	cout << "该二叉树中含有" << count << "个结点" << endl;
	cout << "该二叉树中度为2的结点有" << number << "个" << endl;
	cout << "该二叉树中度为1的结点有" << amount << "个"<<endl;
	cout << "该二叉树中叶子结点有" << count - number - amount << "个" << endl;
	cout << "该二叉树中最大数据值为:" << max << endl;
	cout << "该二叉树中最小数据值为:" << min << endl;
	return 0;
}

运行结果:
在这里插入图片描述

原创文章 23 获赞 8 访问量 1614

猜你喜欢

转载自blog.csdn.net/CSU_hjh/article/details/105801903