数据结构 | 二叉树的各种遍历

数据结构 | 二叉树的各种遍历

我们本章来实现二叉树的这些功能

Tree.h

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int BTDataType;

typedef struct BinaryTreeNode
{
   
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

//创建节点
BTNode* BuyTreeNode(int x);
//创建树
BTNode* CreateTree();
// 二叉树销毁
void BinaryTreeDestory(BTNode* root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);
// 求树的高度
int TreeHeight(BTNode* root);
  • 我们先来几个简单的

创建节点 && 创建树

  • 直接手动个创建即可,很简单~~
//创建节点
BTNode* BuyTreeNode(int x)
{
   
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
   
		perror("malloc fail\n");
		exit(-1);
	}
	root->data = x;
	root->left = NULL;
	root->right = NULL;
	return root;
}
//创建树
BTNode* CreateTree()
{
   
	BTNode* node1 = BuyTreeNode(1);
	BTNode* node2 = BuyTreeNode(2);
	BTNode* node3 = BuyTreeNode(3);
	BTNode* node4 = BuyTreeNode(4);
	BTNode* node5 = BuyTreeNode(5);
	BTNode* node6 = BuyTreeNode(6);
	BTNode* node7 = BuyTreeNode(7);

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

	return node1;
}

二叉树的前中后序遍历

  • 这里也是很简单,也可以看做下图这样遍历,或者画一下递归展开图

在这里插入图片描述

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
   
	if (root == NULL)
	{
   
		printf("NULL ");
		return;
	}

	printf("%d ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
   
	if (root == NULL)
	{
   
		printf("NULL ");
		return;
	}

	BinaryTreeInOrder(root->left);
	printf("%d ", root->data);
	BinaryTreeInOrder(root->right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
   
	if (root == NULL)
	{
   
		printf("NULL ");
		return;
	}

	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%d ", root->data);
}

二叉树节点个数

  • 我们这里看一下递归展开图

在这里插入图片描述

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

二叉树叶子节点个数

  • 为空就返回0
  • 不是空,是叶子,返回1
  • 不是空,也不是叶子,就递归左子树和右子树
int BinaryTreeLeafSize(BTNode* root)
{
   
	// 为空返回0
	if (root == NULL)
		return 0;
	//不是空,是叶子 返回1
	if (root->left == NULL && root->right == NULL)
		return 1;
	// 不是空 也不是叶子  分治=左右子树叶子之和
	return BinaryTreeLeafSize(root->left)
	   	 + BinaryTreeLeafSize(root->right);
}

二叉树第k层节点个数

  • k是1的时候就是一层,就返回1
  • 递归左子树加右子树,每次递归k-1
int BinaryTreeLevelKSize(BTNode* root, int k)
{
   
	if (root == NULL)
		return NULL;

	if (k == 1)
		return 1;

	//递归左子树加右子树,每次递归k-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* ret1 = BinaryTreeFind(root->left, x);
	if (ret1)
		return ret1;
	
	//右子树
	BTNode* ret2 = BinaryTreeFind(root->right, x);
	if (ret2)
		return ret2;

	return NULL;
}

二叉树求树的高度

  • 遍历左子树和右子树(每次遍历都要保存值)
  • 返回最高的那个子树然后加1(根)
int TreeHeight(BTNode* root)
{
   
	if (root == NULL)
		return NULL;

	//遍历左子树和右子树
	int left = TreeHeight(root->left);
	int right = TreeHeight(root->right);

	//返回最高的那个子树然后加1(根)
	return left > right ? left + 1 : right + 1;
}

二叉树的层序遍历

  • 这里的这个层序遍历就需要用到我们之前学过的队列了~~
  • 这里用法是入根(root),然后带孩子节点
void BinaryTreeLevelOrder(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);
}
  • 那如果要一层一层的打印,代码改怎么改呢?
  • 一层一层的带,一层一层的出
// 层序遍历(一层一层的打印)
void _BinaryTreeLevelOrder(BTNode* root)
{
   
	Queue q;
	QueueInit(&q);
	//先入根
	if (root)
		QueuePush(&q, root);

	int leveSize = 1;
	while (!QueueEmpty(&q))
	{
   
		while (leveSize--)
		{
   
			//取队头的数据
			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");
		leveSize = QueueSize(&q);
	}
	QueueDestroy(&q);
}

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

  • 和上面的代码基本一样,取数据如果遇到空就跳出
  • 如果前面遇到空以后,后面还有非空就不是完全二叉树
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(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);

		// 如果是不是空就 return false;
		if (front)
		{
   
			QueueDestroy(&q);
			return false;
		}
	}

	QueueDestroy(&q);
	return true;
}

相关推荐

  1. 数据结构-

    2023-12-06 14:38:04       33 阅读
  2. 数据结构——5.3 和线索

    2023-12-06 14:38:04       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-06 14:38:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-06 14:38:04       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-06 14:38:04       82 阅读
  4. Python语言-面向对象

    2023-12-06 14:38:04       91 阅读

热门阅读

  1. CSS外边距重叠:原理、结果

    2023-12-06 14:38:04       43 阅读
  2. LeetCode1005. Maximize Sum Of Array After K Negations

    2023-12-06 14:38:04       38 阅读
  3. vue打包完成后出现空白页原因及解决

    2023-12-06 14:38:04       64 阅读
  4. 代数学笔记8: Sylow定理

    2023-12-06 14:38:04       46 阅读
  5. Vue2学习笔记(数据监测)

    2023-12-06 14:38:04       57 阅读
  6. 【C/C++】可变参数va_list与格式化输出

    2023-12-06 14:38:04       56 阅读
  7. Windows如何启动MySQL

    2023-12-06 14:38:04       52 阅读
  8. Pytorch:torch.utils.data.random_split()

    2023-12-06 14:38:04       56 阅读
  9. VB.NET二维数组的组合

    2023-12-06 14:38:04       72 阅读
  10. 通俗讲解分布式锁:场景和使用方法

    2023-12-06 14:38:04       46 阅读
  11. 2312skia,12画布包与路径包

    2023-12-06 14:38:04       46 阅读
  12. 大数据(十一):概率统计基础

    2023-12-06 14:38:04       60 阅读