目录

一.链式二叉树新节点的创建

二.链式二叉树的判空

三.链式二叉树的先序遍历

四.链式二叉树的中序遍历

五.链式二叉树的后序遍历

六.链式二叉树的层序遍历

七.链式二叉树叶子节点的计算

八.链式二叉树左孩子节点数计算

九.链式二叉树右孩子节点数计算

十.链式二叉树节点数计算

十一.链式二叉树高度计算

十二.链式二叉树查询某层节点个数

十三.链式二叉树查找节点

十四.判断是否为完全二叉树

十五.实现翻转链式二叉树

十六.链式二叉树的销毁


一.链式二叉树新节点的创建

        创建链式二叉树结点的结构体应该包括:存储数据的数据域data,以及存储左孩子结点地址的指针域left,存储右孩子结点地址的指针域right。

        创建链式二叉树新结点和单链表中创建新结点的处理方法相同。

        代码如下:
 

BTNode* buyNode(char x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	node->data = x;
	node->left = node->right = NULL;

	return node;
}

二.链式二叉树的判空

        链式二叉树的判空只需要返回根节点。

        代码如下:

//判空
bool BTEmpty(BTNode* root)
{
		return (!root);
}

三.链式二叉树的先序遍历

        链式二叉树先序遍历的思路是:先访问根节点,后递归访问左子树,递归访问右子树。

        代码如下:


//前序遍历——根左右
void preOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%c ", root->data);
	preOrder(root->left);
	preOrder(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 leverOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		//取队头,出队头
		 BTNode* top = QueueFront(&q);
		 QueuePop(&q);
		 printf("%c ", top->data);
		 //将队头非空左右孩子入队列
		 if (top->left)
			 QueuePush(&q, top->left);
		 if (top->right)
			 QueuePush(&q, top->right);
	}
	QueueDestroy(&q);
}

七.链式二叉树叶子节点的计算

        叶子节点数 = 左子树的叶子节点数 + 右子树的叶子节点数。

        叶子结点的判断条件是根存在且左右子树都为空。

        代码如下:

// ⼆叉树叶⼦结点个数
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);
}

八.链式二叉树左孩子节点数计算

        根结点的左孩子节点数 = 左子树的左孩子节点数 + 右子树的左孩子节点数。

        左孩子结点的判断条件是根存在且左子树不为空。

        代码如下:

//左孩子节点数
int BinaryTreeLLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->left != NULL)
		return BinaryTreeLLeafSize(root->left) + BinaryTreeLLeafSize(root->right)+1;
	else
		return BinaryTreeLLeafSize(root->left) + BinaryTreeLLeafSize(root->right);
}

九.链式二叉树右孩子节点数计算

        根结点的右孩子节点数 = 左子树的右孩子节点数 + 右子树的右孩子节点数。

        左孩子结点的判断条件是根存在且左子树不为空。

        代码如下:


//右孩子节点数
int BinaryTreeRLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->right != NULL)
		return BinaryTreeRLeafSize(root->left) + BinaryTreeRLeafSize(root->right)+1;
	else
		return BinaryTreeRLeafSize(root->left) + BinaryTreeRLeafSize(root->right);
}

十.链式二叉树节点数计算

        节点数 = 根节点 + 左孩子节点数 + 右孩子节点数。

        根节点要存在。

        代码如下:

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

十一.链式二叉树高度计算

        二叉树的高度为左右子树中的较高子树(用三目操作符即可)再加上根结点自己的高度,即

二叉树的高度 = 左子树的高度 > 右子树的高度 ? 左子树高度 + 1 : 右子树高度 + 1

        代码如下:
 

//⼆叉树的深度/⾼度
int BinaryTreeDepth(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int leftDep = BinaryTreeDepth(root->left);
	int rightDep = BinaryTreeDepth(root->right);

	return 1 + (leftDep > rightDep ? leftDep : rightDep);
}

十二.链式二叉树查询某层节点个数

        根结点的K层节点数 = 左子树的K层节点数 + 右子树的K层节点数。

        判断条件是在K层且结点存在。

        代码如下:
 

// ⼆叉树第k层结点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (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;
	}
	BTNode* leftFind = BinaryTreeFind(root->left, x);
	if (leftFind)
	{
		return leftFind;
	}
	BTNode* rightFind = BinaryTreeFind(root->right, x);
	if (rightFind)
	{
		return rightFind;
	}
	return NULL;
}

十四.判断是否为完全二叉树

        判断二叉树是否为完全二叉树的代码与层序遍历相似,都需要借助数据结构队列,思路是利用完全二叉树的性质:若完全二叉树不为满二叉树,则空节点必定连续出现在最后一层的靠右部分。

        因此利用层序遍历的思路,将所有结点的空孩子也入队,当完全二叉树遍历到第一个空结点时后面一定全为空结点,如果后面还有非空结点,那么这树就不是完全二叉树。

        代码如下:

//判断树是否是完全二叉树
bool TreeComplete(BTNode* root)
{
	//完全二叉树按层序走,非空结点一定是连续的(出过的结点的空子树也被无形中带入队了,不用担心结点在后面没有入队)
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
 
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		
		if (front==NULL)
		{
			break;
		}
		else
		{
			QueuePush(&q, front->left);
			QueuePush(&q, front->right);
		}
	}
 
	//判断是不是完全二叉树(即出队过程中剩余元素有没有非空的结点)
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
 
		//front不为空,就为真,就返回假
		if (front)
		{
			QueueDestroy(&q);
			return false;
		}
	}
 
	QueueDestroy(&q);
	return true;
}

十五.实现翻转链式二叉树

        翻转二叉树 = 翻转左子树 + 翻转右子树。

        和销毁二叉树的思路一致,采用后序遍历的思想,最后翻转根节点的左右子树。

//翻转二叉树
BTNode* InvertTree(BTNode* root)
{
	if (root == NULL)
		return NULL;
	BTNode* tmp = InvertTree(root->right);
	root->right = InvertTree(root->left);
	root->left = tmp;
	return root;
}

十六.链式二叉树的销毁

        二叉树的销毁采用后序遍历的思想,即:先销毁左右子树,再销毁根节点

        代码如下:

// ⼆叉树销毁--左右根
void BinaryTreeDestory(BTNode** root)
{
	if (*root == NULL)
	{
		return;
	}
	BinaryTreeDestory(&((*root)->left));
	BinaryTreeDestory(&((*root)->right));
	free(*root);
	*root = NULL;
}

更多推荐