二叉树的基本操作(创建、销毁、求结点、求叶子、求k层、寻找、前中后序遍历)

相关解析代码中有备注

BinaryTree.h

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef char BTDataType;
typedef struct BinaryTreeNode
{
	struct BinaryTreeNode* _left;
	BTDataType _data;
	struct BinaryTreeNode* _right;
}BTNode;

BTNode* BinaryTreeCreate(BTDataType* a, int* pi);//创建二叉树
void BinaryTreeDestory(BTNode** root);//摧毁二叉树
int BinaryTreeSize(BTNode* root);//求二叉树的结点数
int BinaryTreeLeafSize(BTNode* root);//求二叉树的叶子结点数
int BinaryTreeLevelKSize(BTNode* root, int k);//求二叉树第k层的结点数
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);//找到值为x的结点
void BinaryTreePrevOrder(BTNode* root);//前序遍历
void BinaryTreeInOrder(BTNode* root);//中序遍历
void BinaryTreePostOrder(BTNode* root);//后序遍历

BinaryTree.c

#include"BinaryTree.h"

BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{//传*pi是因为如果是pi,根节点的左边是a[0],左边也有一左一右,也就是一左一右赋值是a[1]和a[2],而根节点的右边还是一开始进来的pi+1,也就是a[1],我们要的应该是a[3]
	assert(a);
	if (a[*pi] != '#')//#视为空格
	{
		BTNode* root = (BTNode*)malloc(sizeof(BTNode));
		root->_data = a[*pi];
		++(*pi); //每插入一个元素都要将输入的数组后移
		root->_left = BinaryTreeCreate(a, pi);
		++(*pi);
		root->_right = BinaryTreeCreate(a, pi);
		return root;
	}
	else //如果是空格就是空
	{
		return NULL;
	}
}

int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;//如果不为空说明本身就是一个有效的结点,所以要加一
}

int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->_left == NULL && root->_right == NULL)
	{
		return 1;//只有左右都为空才是一个叶子,否则根据不同情况继续往下找
	}
	else if (root->_left == NULL)
	{
		return BinaryTreeLeafSize(root->_right);
	}
	else if (root->_right == NULL)
	{
		return BinaryTreeLeafSize(root->_left);
	}
	else
	{
		return BinaryTreeLeafSize(root->_right) + BinaryTreeLeafSize(root->_left);
	}
}

int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}
	if (k <= 0)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
	//第四层相当于第二层的第二层,也就是第二层要再走两层才能到第四层
	//k == 1 代表到了这一层了
}

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->_data == x)
	{
		return root;
	}
	if (BinaryTreeFind(root->_left, x) != NULL)
	{
		return BinaryTreeFind(root->_left, x);
	}
	if (BinaryTreeFind(root->_right, x) != NULL)
	{
		return BinaryTreeFind(root->_right, x);
	}
	return NULL;
}

void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("# ");
	}
	else
	{
		printf("%c ", root->_data);
		BinaryTreePrevOrder(root->_left);
		BinaryTreePrevOrder(root->_right);
	}
}

void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("# ");
	}
	else
	{
		BinaryTreeInOrder(root->_left);
		printf("%c ",root->_data);
		BinaryTreeInOrder(root->_right);
	}
}

void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("# ");
	}
	else
	{
		BinaryTreePostOrder(root->_left);
		BinaryTreePostOrder(root->_right);
		printf("%c ", root->_data);
	}
}

void BinaryTreeDestory(BTNode** root)
{//这里一定要传二级指针,如果是一级指针,在下面的root置为空,只是给函数的指针变量置为空,并没有给我们在外面创建的二叉树的结点的地址置为空
	if (*root)
	{
		BTNode* cur = *root;
		BinaryTreeDestory(&(*root)->_left);
		BinaryTreeDestory(&(*root)->_right);
		free(*root);
		*root = NULL;
	}
}

void BTtest()
{    // 先序遍历:ABD##E#H##CF##G##
	//  中序遍历:#D#B#E#H#A#F#C#G#
	//  后序遍历:##D###HEB##F##GCA
	int pi = 0;
	char a[] = { 'A', 'B', 'D', '#', '#', 'E', '#', 'H', '#', '#', 'C', 'F', '#', '#', 'G', '#', '#' };
	BTNode* root = BinaryTreeCreate(a, &pi);
	int b = BinaryTreeSize(root);
	printf("一共有%d个结点\n", b);
	b = BinaryTreeLeafSize(root);
	printf("一共有%d个叶子结点\n ", b);
	int k = 3;
	b = BinaryTreeLevelKSize(root, k);
	printf("第%d层一共有%d个结点\n ", k, b);
	BTNode* tmp = BinaryTreeFind(root, 'H');
	if (tmp)
		printf("找到了%c \n", tmp->_data);
	else
	{
		printf("没有找到\n");
	}
	BinaryTreePrevOrder(root);
	printf("\n");
	BinaryTreeInOrder(root);
	printf("\n");
	BinaryTreePostOrder(root);
	BinaryTreeDestory(&root);
	printf("\n");
	BinaryTreePrevOrder(root);
	printf("\n");
}
int main()
{
	BTtest();
	system("pause");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我明白了,以下是对应问题的回答: 1、二叉树的建立: 二叉树的建立可以采用递归或非递归方式。递归方式比较简单,对于每个节点,先创建一个节点,然后递归地创建它的左右子树。非递归方式一般使用栈,先将根节点入栈,然后循环执行以下操作:取出栈顶节点,读入它的左右子树(如果有的话),并将它们入栈。直到栈为空为止。 2、叉树叉树的顺是:先访问根节点,然后访问左子树,最后访问右子树。实现方式可以采用递归或非递归方式。 3、叉树叉树的顺是:先访问左子树,然后访问根节点,最后访问右子树。实现方式可以采用递归或非递归方式。 4、后叉树: 后叉树的顺是:先访问左子树,然后访问右子树,最后访问根节点。实现方式可以采用递归或非递归方式。 5、按层叉树: 按层叉树的顺是:从上到下、从左到右依次访问所有节点。实现方式可以采用队列,先将根节点入队,然后循环执行以下操作:取出队头节点,访问它的左右子节点(如果有的话),并将它们入队。直到队列为空为止。 6、叉树的深度: 叉树的深度可以采用递归方式。对于每个节点,它的深度等于左右子树深度的较大值再加1。如果节点为空,则深度为0。 7、指定点到根的路径: 指定点到根的路径可以采用递归方式。对于每个节点,如果它是目标节点或者目标节点的祖先节点,则将它加入路径。如果节点为空,则返回空路径。 8、二叉树销毁: 二叉树销毁可以采用递归方式。对于每个节点,先销毁它的左右子树,然后再销毁它本身。如果节点为空,则直接返回。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值