速通数据结构(七):二叉树

目录

一:前言

二:实现

一:结构

二:生成一个节点

三:建树(随你建)

四:前序中序后序

五:求节点个数

六:叶节点个数

七:求高度

八:二叉树第k层结点个数

九:查找值为x的节点

十:销毁

十一:层序遍历

十二:判断是不是完全二叉树


一:前言

本文我们讲二叉树的另一种实现方式:链式。但是实际上,普通二叉树链式存储没有啥意义,用链表也行,真正有用是加点规则变成搜索二叉树红黑树等等,当然这是后话了。先学学基本链式结构吧。

二:实现

一:结构

typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;//左子树
	struct BinaryTreeNode* right;/右子树
}BTNode;

二:生成一个节点

BTNode* BuyNode(BTDataType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		return NULL;
	}

	node->data = x;
	node->left = NULL;
	node->right = NULL;

	return node;
}

三:建树(随你建)

BTNode* CreatBinaryTree()
{
	BTNode* node1 = BuyNode(10);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(30);
	BTNode* node4 = BuyNode(45);
	BTNode* node5 = BuyNode(50);
	BTNode* node6 = BuyNode(61);
	BTNode* node7 = BuyNode(74);
	BTNode* node8 = BuyNode(80);



	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;
	node5->left = node7;
	node2->right = node7;
	node3->right = node8;

	return node1;
}

这树我随意建的,你想咋建都行~

四:前序中序后序

void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	printf("%d ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
} //前序(根左右)

void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}  //中序(左根右)

void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%d ", root->data);
}  //后序(左右根)

这里用了递归,很方便对吧。咱甚至可以通过看printf的位置来判断前中后序

五:求节点个数

int BTreeSize(BTNode* root)
{
	/*if (root == NULL)
		return 0;

	return BTreeSize(root->left)
		+ BTreeSize(root->right)
		+ 1;*/

	return root == NULL ? 0 : BTreeSize(root->left)
		+ BTreeSize(root->right) + 1;
}

六:叶节点个数

int BTreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	if (root->left == NULL
		&& root->right == NULL)
	{
		return 1;
	}

	return BTreeLeafSize(root->left)
		+ BTreeLeafSize(root->right);
}

七:求高度

int BTreeHeight(BTNode* root)
{
	if (root == NULL)
		return 0;

	int leftHeight = BTreeHeight(root->left);
	int rightHeight = BTreeHeight(root->right);

	return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}

八:二叉树第k层结点个数

int BTreeLevelKSize(BTNode* root, int k)
{
	assert(k > 0);

	if (root == NULL)
		return 0;

	if (k == 1)
		return 1;

	return BTreeLevelKSize(root->left, k - 1)
		+ BTreeLevelKSize(root->right, k - 1);
}

转换成子问题:左子树的k-1层和右子树的k-1层

九:查找值为x的节点

BTNode* BTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;

	if (root->data == x)
		return root;

	BTNode* ret1 = BTreeFind(root->left, x);
	if (ret1)
		return ret1;

	BTNode* ret2 = BTreeFind(root->right, x);
	if (ret2)
		return ret2;

	return NULL;
}

十:销毁

void BTreeDestory(BTNode* root)
{
	if (root == NULL)
		return;

	BTreeDestory(root->left);
	BTreeDestory(root->right);
	free(root);
}

十一:层序遍历

typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;

这里把队列里的数据类型改了下可以用到树中,但是这里为什么不用BTnode呢?因为包头文件时树结构的定义在头文件下边,但是计算机却是向上查找的,所以不用typedef出来的。

void LevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);

	if (root)
		QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		printf("%d ", front->data);

		if (front->left)
			QueuePush(&q, front->left);

		if (front->right)
			QueuePush(&q, front->right);
	}

	printf("\n");

	QueueDestroy(&q);
}

层序遍历要用到队列,出了一个节点,把它左右孩子放进队列,依次出来

十二:判断是不是完全二叉树

bool BTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);

	if (root)
		QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		// 遇到空就跳出
		if (front == NULL)
			break;

		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}

	// 检查后面的节点有没有非空
	// 有非空,不是完全二叉树
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		if (front)
		{
			QueueDestroy(&q);
			return false;
		}
	}

	QueueDestroy(&q);
	return true;
}

这里也要用到层序遍历哦

感谢你看到这,祝大家一起进步!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值