二叉树的相关操作--创建、高度宽度求取、先序、中序、后序、层次遍历

一、二叉树是什么?

二叉树是一种每个结点最多只有两个孩子的树。

满二叉树:所有分支结点的度都为2,且所有的叶子结点均在最底层。

完全二叉树:二叉树中度小于2的结点只出现在最后两层,且最底层的叶子结点都依此排列在该层的最左边位置。

二、二叉树的代码实现

Ps:代码中栈和队列的具体操作都是之前文章写的,可自行查看。

1.二叉树的创建

二叉树有两种存储结构:顺序存储和链式存储。(本文用的链式存储)

代码如下(示例):

struct BiNode {
	char data;
	struct BiNode* lchild, * rchild;        //二叉链表
	int tag = 0;							//用于非递归后序遍历时判断有没有被访问过
	BiNode operator = (BiNode& right)
	{	//重载=
		data = right.data;
		lchild = right.lchild;
		rchild = right.rchild;
		tag = right.tag;
		return *this;
	}
};

void CreateTree(BiNode*& T) {                //采用先序遍历的方式创建
	char x;
	cin >> x;
	if (x == '#') T = NULL;
	else
	{
		T = new BiNode;
		T->data = x;
		CreateTree(T->lchild);
		CreateTree(T->rchild);
	}
}

2.二叉树的高度、宽度

代码如下(示例):

int BiNodeDepth(BiNode* T) {
	//基于后序顺序的二叉树高度计算
	int leftdepth, rigthdepth;
	if (T == NULL) return 0;
	else
	{
		leftdepth = BiNodeDepth(T->lchild);
		rigthdepth = BiNodeDepth(T->rchild);
		return (leftdepth > rigthdepth) ? (leftdepth + 1) : (rigthdepth + 1);//比较该结点右子树和左子树的深度
	}

void BiNodeWidth(BiNode* T) {
	//求树的宽度
	Quene Q;
	InitQuene(Q); 
	int count[10]={0};					//用于存储第几层有几个节点
	EnQuene(Q, T);
	count[0]=1;							//第一层有一个节点
	int x = 1;
	while (!QueneEmpty(Q))
	{
		for (int i = 0; i < count[x - 1]; i++)
		{//每层有几个结点就执行几次,判断是否该层每个结点都有左右子树
			struct BiNode* p = (BiNode*)malloc(sizeof(BiNode));
			DelQuene(Q, p);//将队首元素赋值给p
			if (p != NULL)
			{
				if (p->lchild) count[x]++;//若该结点有左孩子则x层的结点数加1
				if (p->rchild) count[x]++;
				EnQuene(Q, p->lchild);
				EnQuene(Q, p->rchild);
			}
			free(p);
			p = NULL;
		}
		x++;
	}
	int width = 0;
	for (int i = 0; i < x; i++)
	{
		if (count[i] > width) width = count[i];//找到最大结点数即位宽度
	}
	cout << "该树的宽度为:" << width << endl;
}

 3.二叉树的遍历

(1)先序遍历

根节点->左孩子->右孩子

bool PreOrderTraverse(BiNode* T) {
	if (T == NULL) return 0;
	cout << T->data << " ";
	bool l = PreOrderTraverse(T->lchild);
	bool r = PreOrderTraverse(T->rchild);
	return r && l;
}

//非递归
void PreOrderTraverse2(BiNode* T) {
	Quene Q; Stack S;
	InitQuene(Q); InitStack(S);
	EnQuene(Q, T);
	while (!QueneEmpty(Q) || !StackEmpty(S))
	{
		struct BiNode *p=(BiNode*)malloc(sizeof(BiNode));
		if (!QueneEmpty(Q))
		{
			DelQuene(Q, p);
			if (p != NULL)
			{
				cout << p->data << " ";
				EnQuene(Q, p->lchild);//左孩子入队
				PushStack(S, p->rchild);//右孩子入栈
			}
		}
		else
		{
			PopStack(S, p);
			EnQuene(Q, p);
		}
		free(p);
		p = NULL;
	}
	cout << endl;
	//DestoryQuene(Q);
	ClearStack(S);
	DestoryStack(S);
}

(2)中序遍历

左孩子->根节点->右孩子

bool InOrderTraverse(BiNode* T) {
	if (T == NULL) return 0;
	bool l = InOrderTraverse(T->lchild);
	cout << T->data << " ";
	bool r = InOrderTraverse(T->rchild);
	return l && r;
}

//非递归
void InOrderTraverse2(BiNode* T) {
	Stack S;
	InitStack(S);
	while (T != NULL)
	{
		PushStack(S, T);
		T = T->lchild;
	}
	while (!StackEmpty(S))
	{
		struct BiNode* p = (BiNode*)malloc(sizeof(BiNode));
		PopStack(S, p);
		cout << p->data << " ";
		if (p->rchild != NULL)
		{
			p = p->rchild;
			while (p != NULL)
			{
				PushStack(S, p);
				p = p->lchild;
			}
		}
		free(p);
		p = NULL;
	}
	cout << endl;
	ClearStack(S);
	DestoryStack(S);
}

(3)后序遍历

左孩子->右孩子->根节点

bool PostOrderTraverse(BiNode* T) {
	if (T == NULL) return 0;
	bool l = PostOrderTraverse(T->lchild);
	bool r = PostOrderTraverse(T->rchild);
	cout << T->data << " ";
}

//非递归
void PostOrderTraverse2(BiNode* T) {
	Stack S;
	InitStack(S);
	while (T != NULL)
	{
		PushStack(S, T);
		T = T->lchild;
	}
	while (!StackEmpty(S))
	{
		struct BiNode* p = (BiNode*)malloc(sizeof(BiNode));
		PopStack(S, p);
		if (p->rchild != NULL && p->tag == 0)
		{	//如果此节点右孩子存在且没有被访问过
			p->tag = 1;								//表示该节点已被访问过
			PushStack(S, p);
			p = p->rchild;
			while (p != NULL)
			{
				PushStack(S, p);
				p = p->lchild;
			}
		}
		else
		{
			cout << p->data << " ";
		}
		free(p);
		p = NULL;
	}
}

(4)层次遍历

一层一层遍历,从左往右

void leverOrderTraverse(BiNode* T) {
	Quene Q;
	InitQuene(Q);
	EnQuene(Q, T);
	while (!QueneEmpty(Q))
	{
		struct BiNode* p = (BiNode*)malloc(sizeof(BiNode));
		DelQuene(Q, p);
		if (p != NULL)
		{
			cout << p->data << " ";
			EnQuene(Q, p->lchild);
			EnQuene(Q, p->rchild);
		}
		free(p);
		p = NULL;
	}
	cout << endl;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值