C++实现前序建立二叉树,层序遍历,前序中序后序遍历,计算节点数和叶子数,删除二叉树

很多同学在学二叉树的建立,遍历的时候都是看书上的伪代码,虽然能理解,但是不知道怎么把这些伪代码转换成真正的代码运行,这里我们用代码建立二叉树,并用前序遍历输入构建二叉树,层次遍历,前序中序后序遍历依次输出,并计算节点数和叶子数,我们看程序输出的和理论的遍历是否一样。在这里插入图片描述
我们建立一个上图所示这样的二叉树,它的前序遍历是ABDC,但是我们不能直接输入ABDC就建立这样的二叉树,因为如果只知道前序遍历,那所对应的的二叉树有很多种,那怎么解决呢?

我们把这个树扩展,没有左右节点的就用#填充,如下图
在这里插入图片描述

其中空节点我们输入“#”,其他节点输入对应的字母就行了,这样的二叉树的前序遍历是AB#D##C##,这样就可以确定唯一的二叉树了。

这个简单的二叉树层次遍历是ABCD,中序遍历是BDAC,后序遍历是DBCA。

在层次遍历的代码中,我们用了顺序存储结构的队列,层次遍历用队列输出的原理想必大家都知道,这里就不详细叙述了。

接下来就是写代码了

实现代码:

#include <iostream>
#include <cstdlib>
#include <string>
#define ERROR 0
#define OK 1
#define MAXSIZE 100
using namespace std;

typedef char ElemType;/*元素类型默认为char**/
typedef struct BiNode
{
	ElemType data;
	struct BiNode* lchild;
	struct BiNode* rchild;
} BiNode, *BiTree;

typedef struct
{
	BiTree *base;/*重点,队列里面的元素是节点的指针*/
	int front;   
	int rear;
}Squeue;

int InitQueue(Squeue &Q)
{
	Q.base = new BiTree[MAXSIZE];/*队列里面的元素是节点的指针*/
	if (!Q.base) exit(OVERFLOW);
	Q.front = Q.rear = 0;
	return OK;
}

bool isEmpty(const Squeue Q)/*判断队列是否为空*/
{
	return Q.front == Q.rear;
}

bool isFull(const Squeue Q)
{
	return (Q.rear + 1) % MAXSIZE == Q.front;
}

bool EnQueue(Squeue &Q, BiTree tree)/*入队*/
{
	if (isFull(Q))
		return ERROR;

	Q.base[Q.rear] = tree;
	Q.rear = (Q.rear + 1) % MAXSIZE;
	return OK;
}

BiTree Dequeue(Squeue &Q)/*出队,并返回出队的元素*/
{
	if (isEmpty(Q))
		return ERROR;

	BiTree e = Q.base[Q.front];
	Q.front = (Q.front + 1) % MAXSIZE;
	return e;
}

BiTree CreatTree(BiTree tree)/*按照前序遍历的顺序输入,如果没有节点就用#,有节点就用字母*/
{
	ElemType ch;
	cin >> ch;
	if (ch == '#') return NULL;/*如果是*,说明节点为空*/
	else
	{
		tree = new BiNode;
		tree->data = ch;
		tree->lchild = CreatTree(NULL);
		tree->rchild = CreatTree(NULL);
		return tree;
	}
}
void LevelOrderTraverse(BiTree tree)/*层次遍历*/
{
	Squeue Q;
	BiTree T;
	InitQueue(Q);
	if (tree == NULL) return;
	EnQueue(Q, tree);

	while (!isEmpty(Q))/*如果队列不为空,一直出队一个,然后把它的左右指针入队*/
	{
		T = Dequeue(Q);/*出队元素赋值给T*/
		if (T != NULL)/*如果元素不是空指针*/
		{
			cout << T->data;      /*输出节点的数据*/
			EnQueue(Q, T->lchild);/*左孩子入队*/
			EnQueue(Q, T->rchild);/*右孩子入队*/
		}
	}
}

void PreOrderTraverse(BiTree tree)/*前序遍历*/
{
	if (tree == NULL) return;
	cout << tree->data;
	PreOrderTraverse(tree->lchild);
	PreOrderTraverse(tree->rchild);
}
void InOrderTraverse(BiTree tree)/*中序遍历*/
{
	if (tree == NULL) return;
	PreOrderTraverse(tree->lchild);
	cout << tree->data;
	PreOrderTraverse(tree->rchild);
}
void PostOrderTraverse(BiTree tree)/*后序遍历*/
{
	if (tree == NULL) return;
	PostOrderTraverse(tree->lchild);
	PostOrderTraverse(tree->rchild);
	cout << tree->data;
}

int  NodeCount(BiTree tree)/*计算节点数*/
{
	if (tree == NULL) return 0;
	else return (NodeCount(tree->lchild) + NodeCount(tree->rchild) + 1);
}

int yeCount(BiTree tree)/*计算叶子数*/
{
	if (tree == NULL) return 0;
	if (tree->lchild == NULL && tree->rchild == NULL)
		return 1;
	else return(yeCount(tree->lchild) + yeCount(tree->rchild));
}

void DeleteBiTree(BiTree &tree)/*删除叶子*/
{
	if (tree->lchild)
		DeleteBiTree(tree->lchild);
	if (tree->rchild)
		DeleteBiTree(tree->rchild);

	cout << "删除的当前节点是 "<<tree->data << endl;
	delete tree;
	tree = NULL;
}

int main()
{
	cout << "请输入字符" << endl;
	BiTree root = CreatTree(NULL);
	cout << "输入成功" << endl;

	cout << "层次遍历:";
	LevelOrderTraverse(root);
	cout << endl;

	cout << "前序遍历:";
	PreOrderTraverse(root);
	cout << endl;

	cout << "中序遍历:";
	InOrderTraverse(root);
	cout << endl;

	cout << "后序遍历:";
	PostOrderTraverse(root);
	cout<<endl;

	cout<<"节点个数为:"<< NodeCount(root)<<endl;

	cout<<"叶节点个数为:" << yeCount(root)<<endl;

	cout << "删除中..." << endl;
	DeleteBiTree(root);
	if (root == NULL)
		cout << "根节点为空,删除成功!" << endl;

	system("pause");
}

测试结果:
在这里插入图片描述
和理论结果一样。

运行环境:Visual Studio 2017

参考书籍《大话数据结构》

发布了9 篇原创文章 · 获赞 2 · 访问量 669

猜你喜欢

转载自blog.csdn.net/qq_41195985/article/details/103597811