二叉树的基本操作C语言详解

1、链表结构代码

typedef struct Node
{
	char data;								//数据域
	struct Node* Lchild, * Rchild;			//左右孩子指针
}BTNode,*BTree;

2、创建二叉树

int CreateBTree(BTree* T)
{
	char ch;	
	scanf("%c", &ch);
	if (ch == '#')
		*T = NULL;
	else
	{
		*T = (BTree)malloc(sizeof(BTNode));                   //动态申请内存
		if (*T == NULL)
		{
			printf("内存申请失败\n");
			return 0;
		}
		(*T)->data = ch;						 //生成根结点
		CreateBTree(&(*T)->Lchild);				//构造左子树
		CreateBTree(&(*T)->Rchild);				//构造右子树
	}
	return 1;
}

在这里插入图片描述
如需要创建图1的二叉树,就需要输入图二扩展二叉树的前序遍历:AB##C##;

3、销毁

void DestroyBTree(BTree* T)
{
	if (*T)									//双亲结点不为空
	{
		if ((*T)->Lchild)					//左孩子不为空
			DestroyBTree(&(*T)->Lchild);	//销毁左孩子
		if ((*T)->Rchild)					//右孩子不为空
			DestroyBTree(&(*T)->Rchild);	//销毁右孩子
		free(*T);							//销毁双亲结点
		*T = NULL;							//双亲结点指空
	}
}

4、先(前)序遍历

void PreOrderTraverse(BTree T)
{
	if (T)
	{
		printf("%-5c", T->data);				//输出双亲结点
		PreOrderTraverse(T->Lchild);			//遍历左孩子
		PreOrderTraverse(T->Rchild);			//遍历右孩子
	}
}

5、中序遍历

void InOrderTraverse(BTree T)
{
	if (T)
	{
		InOrderTraverse(T->Lchild);					//遍历左孩子
		printf("%-5c", T->data);					//输出双亲结点
		InOrderTraverse(T->Rchild);					//遍历右孩子
	}
}

6、后序遍历

void PostOrderTraverse(BTree T)
{
	if (T)
	{
		PostOrderTraverse(T->Lchild);					//遍历左孩子
		PostOrderTraverse(T->Rchild);					//遍历右孩子
		printf("%-5c", T->data);					//输出双亲结点
	}
}

7、删除左子树

void DeLeftChild(BTree* T)
{
	if (*T)											//双亲结点非空
		DestroyBTree(&((*T)->Lchild));				//销毁左子树		
}

8、删除右子树

void DeRightChild(BTree* T)
{
	if (*T)
		DestroyBTree(&(*T)->Rchild);
}

9、二叉树的深度

int MaxDepth(BTree T) {
	if (T == NULL) {
		return 0;										//返回值传给maxLeft或者maxRight
	}
	else {
		int maxLeft = MaxDepth(T->Lchild);				//maxLeft最终值是0
		int maxRight = MaxDepth(T->Rchild);				//maxRight最终值也是0
		if (maxLeft > maxRight) {						
			return 1 + maxLeft;							//返回双亲结点加上最深子树的深度
		}
		else {
			return 1 + maxRight;
		}
	}
}

10、所有结点个数

int NodeCount(BTree T)
{
	if (T == NULL)
		return 0;
	else
		return NodeCount(T->Lchild) + NodeCount(T->Rchild) + 1;         //返回双亲结点加上左子树和右子树的结点
}

11、度为1的结点个数

int Out1_Count(BTree T)
{
	if (T == NULL)														//空树
		return 0;
	if ((T->Lchild == NULL && T->Rchild != NULL) || (T->Lchild != NULL && T->Rchild == NULL))	//左右孩子有且只有一个
		return Out1_Count(T->Lchild) + Out1_Count(T->Rchild) + 1;			//返回双亲加上子树中度为1的结点
	else
		return Out1_Count(T->Lchild) + Out1_Count(T->Rchild);			//左右孩子都存在,双亲结点出度为二,返回子树
}

12、叶子结点个数

int LeafCount(BTree T)
{
	if (T == NULL)														//空树
		return 0;
	else if (T->Lchild ==NULL && T->Rchild == NULL)						//非空树,但是无孩子
		return 1;													
	else
		return LeafCount(T->Lchild) + LeafCount(T->Rchild);				//有左右孩子
}

13、交换二叉树的左右孩子

int ExchangeTree(BTree* T)
{
	BTree temp;
	if (*T == NULL)									//空树
		return 0;
	else
	{
		temp = (*T)->Lchild;                 //1;swap 三步曲
		(*T)->Lchild = (*T)->Rchild;		//2
		(*T)->Rchild = temp;				//3

		ExchangeTree(&(*T)->Lchild);			//交换左子树
		ExchangeTree(&(*T)->Rchild);			//交换右子树
	}
	return 1;
}

测试

编译环境vc6.0
测试案例:AB#D##C##
在这里插入图片描述
所有代码如下:

/*
纯c语言,广泛使用二级指针,广泛使用递归思想
创建二叉树:以先序遍历创建二叉树,以"#"表示空结点
*/
#include <stdio.h>
#include <stdlib.h>

//*******************1、链表结点结构的定义*****************
typedef struct Node
{
	char data;								//数据域
	struct Node* Lchild, * Rchild;			//左右孩子指针
}BTNode,*BTree;

//******************2、按先序遍历创建二叉树*******************
int CreateBTree(BTree* T)
{
	char ch;	
	scanf("%c", &ch);
	if (ch == '#')
		*T = NULL;
	else
	{
		*T = (BTree)malloc(sizeof(BTNode));                   //动态申请内存
		if (*T == NULL)
		{
			printf("内存申请失败\n");
			return 0;
		}
		(*T)->data = ch;						 //生成根结点
		CreateBTree(&(*T)->Lchild);				//构造左子树
		CreateBTree(&(*T)->Rchild);				//构造右子树
	}
	return 1;
}

//*************************3、销毁*****************
void DestroyBTree(BTree* T)
{
	if (*T)									//双亲结点不为空
	{
		if ((*T)->Lchild)					//左孩子不为空
			DestroyBTree(&(*T)->Lchild);	//销毁左孩子
		if ((*T)->Rchild)					//右孩子不为空
			DestroyBTree(&(*T)->Rchild);	//销毁右孩子
		free(*T);							//销毁双亲结点
		*T = NULL;							//双亲结点指空
	}
}
//******************4、先序遍历	根左右******************
void PreOrderTraverse(BTree T)
{
	if (T)
	{
		printf("%-5c", T->data);				//输出双亲结点
		PreOrderTraverse(T->Lchild);			//遍历左孩子
		PreOrderTraverse(T->Rchild);			//遍历右孩子
	}
}

//******************5、中序遍历	左根右******************
void InOrderTraverse(BTree T)
{
	if (T)
	{
		InOrderTraverse(T->Lchild);					//遍历左孩子
		printf("%-5c", T->data);					//输出双亲结点
		InOrderTraverse(T->Rchild);					//遍历右孩子
	}
}

//******************6、后续遍历	左右根******************
void PostOrderTraverse(BTree T)
{
	if (T)
	{
		PostOrderTraverse(T->Lchild);					//遍历左孩子
		PostOrderTraverse(T->Rchild);					//遍历右孩子
		printf("%-5c", T->data);					//输出双亲结点
	}
}

//******************7、删除左子树******************
void DeLeftChild(BTree* T)
{
	if (*T)											//双亲结点非空
		DestroyBTree(&((*T)->Lchild));				//销毁左子树		
}

//******************8、删除右子树******************
void DeRightChild(BTree* T)
{
	if (*T)
		DestroyBTree(&(*T)->Rchild);
}
//*****************9、二叉树的深度*******************
int MaxDepth(BTree T) {
	if (T == NULL) {
		return 0;										//返回值传给maxLeft或者maxRight
	}
	else {
		int maxLeft = MaxDepth(T->Lchild);				//maxLeft最终值是0
		int maxRight = MaxDepth(T->Rchild);				//maxRight最终值也是0
		if (maxLeft > maxRight) {						
			return 1 + maxLeft;							//返回双亲结点加上最深子树的深度
		}
		else {
			return 1 + maxRight;
		}
	}
}

//*******************10、二叉树结点个数*****************
int NodeCount(BTree T)
{
	if (T == NULL)
		return 0;
	else
		return NodeCount(T->Lchild) + NodeCount(T->Rchild) + 1;         //返回双亲结点加上左子树和右子树的结点
}

//*******************11、二叉树度为1的结点个数*****************
int Out1_Count(BTree T)
{
	if (T == NULL)														//空树
		return 0;
	if ((T->Lchild == NULL && T->Rchild != NULL) || (T->Lchild != NULL && T->Rchild == NULL))	//左右孩子有且只有一个
		return Out1_Count(T->Lchild) + Out1_Count(T->Rchild) + 1;			//返回双亲加上子树中度为1的结点
	else
		return Out1_Count(T->Lchild) + Out1_Count(T->Rchild);			//左右孩子都存在,双亲结点出度为二,返回子树
}

//******************12、二叉树叶子结点个数******************
int LeafCount(BTree T)
{
	if (T == NULL)														//空树
		return 0;
	else if (T->Lchild ==NULL && T->Rchild == NULL)						//非空树,但是无孩子
		return 1;													
	else
		return LeafCount(T->Lchild) + LeafCount(T->Rchild);				//有左右孩子
}

//*****************13、交换二叉树的左右孩子*******************
int ExchangeTree(BTree* T)
{
	BTree temp;
	if (*T == NULL)									//空树
		return 0;
	else
	{
		temp = (*T)->Lchild;                 //1;swap 三步曲
		(*T)->Lchild = (*T)->Rchild;		//2
		(*T)->Rchild = temp;				//3

		ExchangeTree(&(*T)->Lchild);			//交换左子树
		ExchangeTree(&(*T)->Rchild);			//交换右子树
	}
	return 1;
}

int main()
{
	BTree T;
	printf("输入待创建二叉树的先序序列:\n");
	CreateBTree(&T);
	printf("先序遍历\n");
	PreOrderTraverse(T);
	printf("\n中序遍历\n");
	InOrderTraverse(T);
	printf("\n后续遍历\n");
	PostOrderTraverse(T);

	printf("\n二叉树的深度为:%d",MaxDepth(T));
	printf("\n结点个数为:%d", NodeCount(T));
	printf("\n度为1的结点个数:%d", Out1_Count(T));
	printf("\n叶子结点个数:%d", LeafCount(T));

	DeLeftChild(&T);
	printf("\n删除左子树后二叉树的结点个数为:%d\n", NodeCount(T));
	return 0;
}

测试结果:
在这里插入图片描述

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值