二叉树的常见操作

二叉树的一些常见操作:

typedef char BTDataType;//二叉树的元素类型
typedef struct BinaryTreeNode {
	struct BinaryTreeNode* left;// 左子树
	struct BinaryTreeNode* right;//右子树
	BTDataType data;
}BTNode;

void BTNodeInit(BTNode* bt, BTDataType x)//初始化
{
	bt->left = NULL;
	bt->right = NULL;
	bt->data = x;
}

int TreeSize(BTNode* root)//返回树的结点个数
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
int TreeLeafSize(BTNode* root)//叶子结点个数
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

int TreeDepth(BTNode* root)//返回树的深度
{
	if (root == NULL)return 0;
	int leftDepth = TreeDepth(root->left);//左树的深度
	int rightDepth = TreeDepth(root->right);//右树的深度
	return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;//树的深度=左树的深度+右树的深度+1
}

void Destroy(BTNode* root)//销毁树
{
	if (root == NULL)return;
	Destroy(root->left);
	Destroy(root->right);
	free(root);
	root = NULL;
}
//使用括号表示法输入二叉树并转化为二叉树的链式存储结构
BTreeCreat(BTNode** root, int* pi, char* a)
{
	//核心思路:
	 //'('表示开辟一个新节点链接在双亲节点的左孩子上,然后把双亲节点存入栈
	 //','表示开辟一个新节点链接在双亲节点的右孩子上
	 //')'表示双亲节点链接结束,把双亲节点取出栈
	if (root == NULL)return;
	ST st;//创建一个栈
	QueueInit(&st);//初始化栈
	int k = 1;//k用来判断节点是在左子树还是右子树,当k为1时在左子树,当k为2时在右子树
	(*root)->data = a[(*pi)++];//把根节点1存进去
	BTNode* newroot = *root;//newroof表示新节点的双亲结点
	while (a[(*pi)])
	{
		if (a[*pi] == '(')
		{
			StackPush(&st, newroot);//把双亲节点插入栈
			(*pi)++;
			k = 1;
		}
		if (a[*pi] == ',')
		{
			(*pi)++;
			k = 2;
		}
		if (a[*pi] == ')')
		{
			(*pi)++;
			StackPop(&st);//把双亲节点拿出栈
			continue;
		}
		newroot = (BTNode*)malloc(sizeof(BTNode));//创建一个新节点
		newroot->left = NULL;
		newroot->right = NULL;
		newroot->data = a[*pi];//把数据存进去
		if (k == 1)
		{
			StackTop(&st)->left = newroot;//把新节点链接在双亲节点的左孩子上
		}
		if (k == 2)
		{
			StackTop(&st)->right = newroot;//把新节点链接在双亲节点的右孩子上
		}

		(*pi)++;
	}
	StackDestroy(&st);//销毁栈
}

二叉树的遍历:

二叉树的前中后序遍历,采用的是分而治之的思路,从根节点开始分为根、左子树、右子树,然后向下递归,直至叶子结点返回。

void PrevOrder(BTNode* root)//前序 根->左 ->右
{
	if (root == NULL)
	{
		//printf("NULL ");
		return;
	}
	printf("%c ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}
void InOrder(BTNode* root)//中序 左->根->右
{
	if (root == NULL)
	{
		//printf("NULL ");
		return;
	}
	InOrder(root->left);
	printf("%c ", root->data);
	InOrder(root->right);
}
void PostOrder(BTNode* root)//后序 左->右->根
{
	if (root == NULL)
	{
		//printf("NULL ");
		return;
	}
	PostOrder(root->left);
	PostOrder(root->right);
	printf("%c ", root->data);
}
void LevelOrder(BTNode* root)
{
	Queue q;//创建一个队列
	QueueInit(&q);//初始化队列
	//层序遍历核心思路上一层出的时候带下一层进
	if (root)
	{
		QueuePush(&q, root);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* Front = QueueFront(&q);//把队列里的head->data即A赋值给Front
		QueuePop(&q);//释放head
		printf("%c ", Front->data);
		//把下一层带进去
		if (Front->left)QueuePush(&q, Front->left);
		if (Front->right)QueuePush(&q, Front->right);
	}
	printf("\n");
	QueueDestroy(&q);
}

判断二叉树是否为平衡二叉树:

//平衡树:左树右树的高度差不超过1,并且子树也为平衡树
bool TreeisBlanced(BTNode* root)//判断是否为平衡树 是返回true 不是返回false
{
	if (root)return true;
	int leftDepth = TreeDepth(root->left);
	int rightDepth = TreeDepth(root->right);
	return abs(leftDepth - rightDepth) < 2 //abs()是一个求绝对值的函数,判断左树右树的高度差是否超过1
		&& TreeisBlanced(root->left)//判断左树是否为平衡树
		&& TreeisBlanced(root->right);//判断右树是否为平衡树
}

判断该二叉树是否为完全二叉树

//判断该二叉树是否为完全二叉树
bool BTIsComplete(BTNode*root)
{
	//思路:在层序遍历的基础上找不饱和节点,不饱和节点之后的节点必须为空
	Queue q;
	QueueInit(&q);
	if (root == NULL)return;
	QueuePush(&q, root);
	int k = 0;//k=0表示节点饱和,k=1表示已有不饱和的节点
	while (!QueueEmpty(&q))
	{
		BTNode* newroof = QueueFront(&q);
		QueuePop(&q);
		if (k == 1)
		{
			if (newroof->left != NULL || newroof->right != NULL)
			{
				QueueDestroy(&q);//每次返回前都要销毁栈,防止空间泄露
				return false;
			};
		}
		//先找到一个不饱满的节点
		if (newroof->left == NULL || newroof->right == NULL)//子节点有一个为空的即为不饱和节点
		{
			if (newroof->left == NULL && newroof->right != NULL)//当左孩子为空右孩子不为空时,不是完全二叉树
			{
				QueueDestroy(&q);
				return false;
			}
			k = 1;
		}
		if (newroof->left != NULL)
		{
			QueuePush(&q, newroof->left);
		}
		if (newroof->right != NULL)
		{
			QueuePush(&q, newroof->right);
		}
	}
	return true;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LQB木杉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值