链式二叉树(C语言数据结构)

前言:

        前期学习二叉树,包括堆,都是利用数组实现。

        接下来就用链表的形式实现二叉树,并实现二叉树的相关功能

二叉树前序遍历:

        什么是前序遍历,任何一棵二叉树都可以分为根和左子树、右子树。

例如:

前序遍历的顺序:根   左子树   右子树

例如如下二叉树前序遍历顺序

如果想要前序遍历一个二叉树代码如下:

void pre_order(BTNode*Node)
{
	if (Node == NULL)
	{
		return;
	}
	printf("%d ",Node->_data);
	pre_order(Node->_left);
	pre_order(Node->_right);
}

利用前序遍历插入数据:

将ABD##E#H##CF##G##(#表示NULL)通过前序遍历插入

代码如下:
 

BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{
	assert(a);
	if (a[*pi] == '#')
	{
		(*pi)++;
		return NULL;
	}
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		perror("malloc::error");
		exit(-1);
	}
	root->_data = a[(*pi)++];
	root->_left = BinaryTreeCreate(a,pi);
	root->_right = BinaryTreeCreate(a,pi);
	return root;
}

二叉树的中序遍历、后序遍历:

        有了前序遍历的经验,中序后序遍历就不难写出。

        中序遍历访问顺序:左子树   根   右子树

         后序遍历访问顺序:左子树  右子树  根

代码如下:

//中序遍历
void middle_order(BTNode*root)
{
	if (root == NULL)
	{
		return;
	}
	middle_order(root->_left);
	printf("%c ", root->_data);
	middle_order(root->_right);
}
//后序遍历
void post_order(BTNode*root)
{
	if (root == NULL)
	{
		return;
	}
	post_order(root->_left);
	post_order(root->_right);
	printf("%c ", root->_data);
}

 二叉树的销毁:

思路:

1、必须先释放左右孩子,最后释放根,不然会导致根丢失,找不到孩子了。

2、如果根的左右孩子都为空,则释放空间并返回。

代码如下:

void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
		return;
	if (root->_left == NULL && root->_right == NULL)
	{
		free(root);
		root = NULL;
		return;
	}
	BinaryTreeDestory(root->_left);
	BinaryTreeDestory(root->_right);
}

二叉树节点个数:

思路:

      1、  需要遍历,将一个二叉树看作一个根一个左孩子和一个右孩子。

       2、 左孩子的节点个数+有孩子的节点个数+本身(1)。

代码如下:

int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}

二叉树叶子节点个数:

思路:

1、当根的左孩子和右孩子都等于NULL时,返回1;

2、当根为NULL时,返回0;

代码如下:

int BinaryTreeLeafSize(BTNode* root)
{
	if(root == NULL)
	{
		return 0;
	}
	if (root->_left == NULL && root->_right == NULL)
	{
		return 1;
	}
	return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}

二叉树第k层的节点数:

思路:

1、如果是第一层直接返回1

2、如果不是第一层,则为左孩子的第k层的节点数+有右孩子的第k层的节点数

代码如下:

int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (k == 0||root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return BinaryTreeLevelKSize(root->_left, k-1) + BinaryTreeLevelKSize(root->_right, k-1);
}

二叉树查找值为x的节点:

代码如下:
 

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

*二叉树层序遍历:

 思路:

               这里由于是初阶,层序遍历我们借助队列层序遍历。

主要思路:
一个节点不为空就要进队列,然后记录之后pop

如果一个节点的左右节点不为空,就让左右孩子进去。

代码如下:
 

void BinaryTreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%c ", front->_data);
		if(front->_left)
			QueuePush(&q, front->_left);
		if (front->_right)
			QueuePush(&q, front->_right);
		printf("\n");
	}
	QueueDestroy(&q);
}

判断一个二叉树是否为完全二叉树:

思路:

        借助层序遍历的思想,如果一个二叉树只有右孩子没有左孩子,那么当前二叉树不是完全二叉树。

代码如下:

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front->_left)
			QueuePush(&q, front->_left);
		if (front->_right)
			QueuePush(&q, front->_right);
		if (front->_left == NULL && front->_right != NULL)
			return 0;
	}
	return 1;
	QueueDestroy(&q);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值