二叉树的基本运算(涉及递归均有给出模型)

本文详细介绍了二叉树的定义、存储结构以及链式存储下的基本操作,包括创建二叉树、销毁二叉树、查找节点、计算高度和输出二叉树。主要通过递归实现这些功能,并提供了创建二叉树和销毁二叉树的示例代码。
摘要由CSDN通过智能技术生成

目录

介绍:

二叉树的基本运算及其实现:

BTNode* CreateBTree(char* str) 创建二叉树

void DestroyBTree(BTNode* b) 销毁二叉树

BTNode* FindNode(BTNode* b, ElemType x) 查找结点

BTNode* LchildNode(BTNode* p) 查找左孩子结点

BTNode* RchildNode(BTNode* p) 查找右孩子结点

int BTHeight(BTNode* b) 求二叉树b的高度

最后总代码:

结语:


介绍:

二叉树的定义:二叉树由一个根结点和两棵互不相交的称为左子树(left subtree)和右子树(right subtree)的二叉树组成。

二叉树的存储结构:

(1)循序存储:(因其在极端条件下空间浪费极大故大部分二叉树都采用链式存储结构)

(2)链式存储

typedef struct node
{
    ElemType data;       //数据元素
    struct node* lchild;    //指向左孩子结点
    struct node* rchild;    //指向右孩子结点
}BTNode;     //二叉树的结构体

二叉树的基本运算及其实现:

特别说明下面运算均采用二叉链存储结构进行存储。

BTNode* CreateBTree(char* str) 创建二叉树

void DestroyBTree(BTNode* b) 销毁二叉树

BTNode* FindNode(BTNode* b, ElemType x) 查找结点

BTNode* LchildNode(BTNode* p) 查找左孩子结点

BTNode* RchildNode(BTNode* p) 查找右孩子结点

int BTHeight(BTNode* b) 求二叉树b的高度

void DispBTree(BTNode* b) 以括号表示法输出二叉树

既然使用二叉链来进行实现的,那么必然就离不开链表,提到链表就不得不想到结构体。那么我们二叉树的结构体就来啦👀

说明:为了使描述简单故基本类型采用char类型,如果大家想修改的话把上面的char改成其它即可。

#define MaxSize 100
typedef char ElemType;
typedef struct node
{
	ElemType data;
	struct node* lchild;
	struct node* rchild;
}BTNode;

BTNode* CreateBTree(char* str) 创建二叉树

采用括号表达式法表示二叉树,用ch遍历str,因为使括号表达式所以其中只有四类字符,例如下图:

其处理方式如下。

1:若ch=‘(’,表示前面的结点p存在孩子结点需要将其进栈(括号表达式一般都是要用到栈的)。

2:若ch=‘)’,表示以栈顶结点为根节点的子树创建完毕,将其退栈。

3:若ch=‘,’,表示要处理栈顶结点的有孩子结点,故置k=2

4:其它情况:只能是单个字符,对应二叉树中的某个结点值,需要创建一个结点p来存储该结点值。根据k值建立它与栈顶结点之间的联系。当k=1时,将结点p作为栈顶结点的左孩子;当k=2时,将结点p作为栈顶结点的右孩子。

用一个while把str数组全部遍历采用上面四条处理方法,我们的二叉树就创建好啦👌!!!

代码如下:

BTNode* CreateBTree(char* str)
{
	BTNode* b;
	BTNode* St[MaxSize];
	BTNode* p=NULL;
	int top = -1, k, j = 0;
	char ch;
	b = NULL;
	ch = str[j];
	while (ch != '\0') 
	{
		switch (ch)
		{
		case '(':top++; St[top] = p; k = 1; break;
		case ')': top--; break;
		case ',':k = 2; break;
		default:
		{
			p = (BTNode*)malloc(sizeof(BTNode));
			p->data = ch;
			p->lchild = p->rchild = NULL;
			if (b == NULL)
				b = p;
			else
			{
				switch (k)
				{
				case 1:St[top]->lchild = p; break;
				case 2:St[top]->rchild = p; break;
				}
			}
		}
		}
		j++;
		ch = str[j];
	}
	return b;
}

void DestroyBTree(BTNode* b) 销毁二叉树

创建讲完,那么销毁必然少不了,想亲兄弟一样(形象吧(❁´◡`❁))


处理方式如下:二叉树最经常用到的莫过于递归了,没错我们的销毁就是用递归来完成的。

递归那么最重要的一定是思路,建议大家遇到递归的时候一定要在草稿纸上列出递归的模型,尤其是递归的出口一定要设置好!!!(下面我给出我的递归模型大家可以参考参考)

当b为NULL时什么也不做,当b不等于NULL时先释放左孩子子树的空间,再释放右孩子子树的空间,最后再释放b树的空间,为什么要按照这个循序呢?这是因为如果先释放了b那么我们的左右孩子子树就找不到了,那么内存就会泄露。(这个递归其实总的就执行free(b))

代码如下:

void DestroyBTree(BTNode* b)
{
	if (b != NULL)
	{
		DestroyBTree(b->lchild);
		DestroyBTree(b->rchild);
		free(b);
	}
	return;
}

BTNode* FindNode(BTNode* b, ElemType x) 查找结点

其功能是在二叉树b中查找值为x的结点,找到后返回其地址,否则返回NULL。

处理方式如下:没错这里的实现又是递归。对于递归的解释在上面的销毁哪我已经讲的很清楚了,故这里不在过多赘述。递归的模型如下:

对着上面的这张图,那么代码实现就非常简单啦🤳🤳🤳

代码如下:

BTNode* FindNode(BTNode* b, ElemType x)
{
	BTNode* p;
	if (b == NULL) return NULL;
	else if (b->data == x) return b;
	else
	{
		p = FindNode(b->lchild, x);
		if (p != NULL) return p;
		else return FindNode(b->rchild,x);
	}
}

BTNode* LchildNode(BTNode* p) 查找左孩子结点

BTNode* RchildNode(BTNode* p) 查找右孩子结点

由于这两个基本算法的实现和功能基本一致故这里我们两个一起来(因为简单故直接上代码)

代码如下:

BTNode* LchildNode(BTNode* p)
{
	return p->lchild;
}
BTNode* RchildNode(BTNode* p)
{
	return p->rchild;
}

int BTHeight(BTNode* b) 求二叉树b的高度

有树那么就有高度,高的树价值大,高的二叉树占的空间大。

处理方法:递归实现,递归的模型如下:

依图代码实现如下:

特别注意:规定空树的高度为0,只有一个根高度为1

int BTHeight(BTNode* b)
{
	int lchildh, rchildh;
	if (b == NULL) return 0;
	else
	{
		lchildh = BTHeight(b->lchild);
		rchildh = BTHeight(b->rchild);
		return (lchildh > rchildh) ? (lchildh + 1) : (rchildh + 1);
	}
}

void DispBTree(BTNode* b) 以括号表示法输出二叉树

最后就是输出二叉树了,实现方法:递归,有孩子结点时才输出‘(’,递归输出左子树,有右孩子结点才输出‘,’,递归输出右子树,有孩子结点时才输出‘)’。具体递归模型如下:

因为存储时,我们并没有存储括号和逗号,故在输出时,我们要人为的给它们加上。

具体代码实现如下:

void DispBTree(BTNode* b)
{
	if (b != NULL)
	{
		printf("%c", b->data);
		if (b->lchild != NULL || b->rchild != NULL)
		{
			printf("(");
			DispBTree(b->lchild);
			if (b->rchild != NULL) printf(",");
			DispBTree(b->rchild);
			printf(")");
		}
	}
}

最后总代码:

有给出括号表达式供大家进行代码调试并理解代码。

#define  _CRT_SECURE_NO_WARNINGS 1
//二叉树的基本运算
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node
{
	ElemType data;
	struct node* lchild;
	struct node* rchild;
}BTNode;
BTNode* CreateBTree(char* str)
{
	BTNode* b;
	BTNode* St[MaxSize];
	BTNode* p=NULL;
	int top = -1, k, j = 0;
	char ch;
	b = NULL;
	ch = str[j];
	while (ch != '\0') 
	{
		switch (ch)
		{
		case '(':top++; St[top] = p; k = 1; break;
		case ')': top--; break;
		case ',':k = 2; break;
		default:
		{
			p = (BTNode*)malloc(sizeof(BTNode));
			p->data = ch;
			p->lchild = p->rchild = NULL;
			if (b == NULL)
				b = p;
			else
			{
				switch (k)
				{
				case 1:St[top]->lchild = p; break;
				case 2:St[top]->rchild = p; break;
				}
			}
		}
		}
		j++;
		ch = str[j];
	}
	return b;
}
void DestroyBTree(BTNode* b)
{
	if (b != NULL)
	{
		DestroyBTree(b->lchild);
		DestroyBTree(b->rchild);
		free(b);
	}
	return;
}
BTNode* FindNode(BTNode* b, ElemType x)
{
	BTNode* p;
	if (b == NULL) return NULL;
	else if (b->data == x) return b;
	else
	{
		p = FindNode(b->lchild, x);
		if (p != NULL) return p;
		else return FindNode(b->rchild,x);
	}
}
BTNode* LchildNode(BTNode* p)
{
	return p->lchild;
}
BTNode* RchildNode(BTNode* p)
{
	return p->rchild;
}
int BTHeight(BTNode* b)
{
	int lchildh, rchildh;
	if (b == NULL) return 0;
	else
	{
		lchildh = BTHeight(b->lchild);
		rchildh = BTHeight(b->rchild);
		return (lchildh > rchildh) ? (lchildh + 1) : (rchildh + 1);
	}
}
void DispBTree(BTNode* b)
{
	if (b != NULL)
	{
		printf("%c", b->data);
		if (b->lchild != NULL || b->rchild != NULL)
		{
			printf("(");
			DispBTree(b->lchild);
			if (b->rchild != NULL) printf(",");
			DispBTree(b->rchild);
			printf(")");
		}
	}
}
int main()
{
	char str[] = "A(B(D(,G)),C(E,F))";
	BTNode* b = CreateBTree(str);
	DispBTree(b);
	return 0;
}

以上便是二叉树的基本运算,那么我们的文章就好这里结束啦🎉🎉🎉

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。

  • 33
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
很抱歉,作为一名AI语言模型,我无法在本平台上为您编写和运行C++程序,但是我可以为您提供一些指导,帮助您完成这些任务。 1. 实现二叉树运算功能 实现二叉树运算功能,需要定义二叉树数据结构,并实现相应的操作函数。二叉树数据结构可以定义为一个结构体,包含一个指向左子树的指针,一个指向右子树的指针,以及一个存储节点值的变量。 2. 输出二叉树 输出二叉树可以采用凹入表示法,也可以采用其他方式。凹入表示法是指将二叉树的每个节点按照深度依次排列,并在每个节点前加入一定数量的空格,以便于观察二叉树的结构。 3. 输出某个节点的左右孩子节点 输出某个节点的左右孩子节点,可以先查找该节点,然后输出该节点的左右子树的节点值。 4. 输出二叉树的高度 输出二叉树的高度可以采用递归的方式求解。对于一个节点,它的高度等于左右子树中高度较大的值加1。 5. 释放二叉树 释放二叉树可以采用递归的方式,依次释放每个节点的左右子树,然后释放该节点本身。 6. 构造二叉树并输出 给定二叉树的先序序列和中序序列,可以通过递归的方式构造二叉树。具体的实现方法可以参考以下步骤: - 从先序序列中取出第一个元素作为根节点。 - 在中序序列中查找根节点的位置,将中序序列分成左子树和右子树两部分。 - 递归构造左子树和右子树。 - 输出二叉树的括号表示法。 以上是一些基本的实现思路,具体的实现细节需要根据实际情况进行调整和完善。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值