【数据结构】遍历二叉树(递归思想)-->赋源码

欢迎来到我的Blog,点击关注哦💕

前言

二叉树遍历是指按照一定的顺序访问二叉树中的每个节点,使得每个节点恰好被访问一次。遍历是二叉树上最重要的运算之一,是二叉树上进行其他运算的基础。

一、二叉树遍历概念

在这里插入图片描述

二叉树遍历分类

  • 前序遍历 :根节点–>左子树–>右子树。在前序遍历时,首先访问根节点,然后依次访问左子树和右子树。
  • 中序遍历 : 左子树–>根节点–>右子树。在中序遍历时,首先访问左子树,然后访问根节点,最后访问右子树。
  • 后序遍历:左子树–>右子树–>根节点。在后序遍历时,首先访问左子树和右子树,然后访问根节点。
  • 层序遍历: 由顶层到底层,一层一层遍历。

二叉树其他操作

树节点的个数树深度树 k 层的个数查找节点

二、二叉树遍历实现

我们以下面为例子:

1
2
3
4
5
6
7
8
9
2_right_NULL
3_left_NULL

2.1 二叉树建立

1.定义一个结构体,分别有左右两个指针。

2.为每一个节点创建孔家。

3.创建二叉树,并如上图连接。

//定义结构体typedef int BTTypeData;typedef struct BinaryTree
{BTTypeData data;struct BinaryTree* left;struct BinaryTree* right;
}BinaryTree;//创建空间BinaryTree* BuyBinaryTree(BTTypeData x)
{BinaryTree* node = (BinaryTree*)malloc(sizeof(BinaryTree));if (node == NULL){perror("malloc fail");return NULL;}node->data = x;node->left = NULL;node->right = NULL;return node;
}//建树BinaryTree* CreateBinaryTree()
{BinaryTree* node1 = BuyBinaryTree(1);BinaryTree* node2 = BuyBinaryTree(2);BinaryTree* node3 = BuyBinaryTree(3);BinaryTree* node4 = BuyBinaryTree(4);BinaryTree* node5 = BuyBinaryTree(5);BinaryTree* node6 = BuyBinaryTree(6);BinaryTree* node7 = BuyBinaryTree(7);BinaryTree* node8 = BuyBinaryTree(8);BinaryTree* node9 = BuyBinaryTree(9);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;node3->right = node7;node6->left = node8;node6->right = node9;return node1;
}

2.2 前序遍历

在递归实现中,前序遍历的基本思想是对于每一个节点,先访问该节点,然后对其左子树进行前序遍历,最后对其右子树进行前序遍历。如果当前节点为空,则直接返回。这种方法的优点是代码简洁明了,易于理解,但缺点是可能导致栈溢出,特别是在处理深度较大的二叉树时。

遍历结果:1–> 2–> 3 –>7 –>4 –>5 –>6–> 8 –>9

//前序遍历
void PreOrder(BinaryTree* root)
{if (root == NULL){//printf("NULL ");return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);
}

2.2 中序遍历

首先对左子树进行中序遍历,然后访问根节点,最后对右子树进行中序遍历。

遍历结果:3 –>7–>2–> 1–> 5–> 4–>8–> 6–> 9

void InOrder(BinaryTree* root)
{if (root == NULL){//printf("NULL ");return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);}

2.3 后序遍历

递归函数首先访问左子树,然后访问右子树,最后访问根节点。如果当前节点为空,则直接返回。

遍历结果:7–> 3–> 2–> 5–> 8 –>9 –>6 –>4 –>1

//后序遍历
void PostOrder(BinaryTree* root)
{if (root == NULL){//printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);}

2.4 层序遍历

在二叉树的层序遍历是指按照树的层次顺序,从上到下、从左到右逐层访问二叉树的节点。这种遍历方式可以帮助我们了解二叉树的结构布局,特别是在处理树状数据结构时非常有用。

利用队列的特点,有关队列可参考 栈和队列

  • 将根节点入队。

  • 当队列不为空时,从队列中取出一个节点,访问该节点。

  • 将该节点的左右子节点(如果存在)入队。

  • 重复步骤2和3,直到队列为空。

遍历结果:1–> 2 –>4 –>3 –>5 –>6 –>7 –>8 –>9

//层序遍历void LevelOrder(BinaryTree* root)
{if (root == NULL){printf("NULL ");return;}Queue TBT;QueueInit(&TBT);if (root)QueuePush(&TBT, root);while (!QueueEmpty(&TBT)){BinaryTree* front = QueueTop(&TBT);QueuePop(&TBT);printf("%d ", front->data);if (front->left)QueuePush(&TBT, front->left);if (front->right)QueuePush(&TBT, front->right);}QueueDestroy(&TBT);}

2.5 二叉树的节点个数

利用递归的方法,左右子树调用,如果该节点为NULL 便会返回0,否则返回1。

//树的结点个数int TreeSize(BinaryTree* root)
{return root == 0 ? 0:TreeSize(root->left) + TreeSize(root->right) + 1;}

2.6 二叉树的深度

利用 leftright记录左右子树的个数,然后比较 选择较大的一个。

如图:在这里插入图片描述

//树的高度int TreeHeight(BinaryTree* root)
{if (root == NULL){return 0;}int left = TreeHeight(root->left) ;int right = TreeHeight(root->right);return left > right ? left + 1 : right + 1;}

2.7 二叉树第K层的个数

假设查找第三层,K为3 ,每次递归K–,知道K== 1 的时候 返回1。

//层的个数int TreeKLevel(BinaryTree* root, int k)
{if (root == NULL){return 0;}if (k == 1){return 1;}return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);}

2.8 二叉树查找结点

节点的查找,如果节点为NULL饭后NULL,如果此节点的data等于x,返回节点的地址。

//查找节点BinaryTree* TreeFind(BinaryTree* root, BTTypeData x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BinaryTree* lret = TreeFind(root->left, 7);if (lret)return lret;BinaryTree* rret = TreeFind(root->right, 7);if (rret)return rret;return NULL;
}

源码

queue.c

#define _CRT_SECURE_NO_WARNINGS#include "queue.h"//初始化
void QueueInit(Queue* ps)
{assert(ps);ps->head = ps->tail = NULL;ps->szie = 0;}//销毁
void QueueDestroy(Queue* ps)
{assert(ps);QNode* cur = ps->head;while (cur){QNode* next = cur->next;free(cur);cur = next;}ps->head = ps->tail = NULL;ps->szie = 0;
}//入队
void QueuePush(Queue* ps,QDataType x)
{assert(ps);QNode* newcode = (QNode*)malloc(sizeof(QNode));if (newcode == NULL){perror("malloc fail");return ;}newcode->next = NULL;newcode->data = x;if (ps->head == NULL){ps->head = ps->tail = newcode;}else{ps->tail->next = newcode;ps->tail = newcode;}ps->szie++;}//删除
void QueuePop(Queue* ps)
{assert(ps);assert(ps->head != NULL);assert(!QueueEmpty(ps));if (ps->head->next == NULL){free(ps->head);ps->head = ps->tail = NULL;}else{QNode* next = ps->head->next;free(ps->head);ps->head = next;}ps->szie--;
}//大小
int QueueSize(Queue* ps)
{assert(ps);return ps->szie;
}//判空队
bool QueueEmpty(Queue* ps)
{assert(ps);return ps->szie == 0;
}//出队头
QDataType QueueTop(Queue* ps)
{assert(ps);assert(!QueueEmpty(ps));return ps->head->data;
}//出队尾
QDataType QueueBack(Queue* ps)
{assert(ps);return ps->tail->data;
}

queue.h

#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>typedef struct BinaryTree* QDataType;typedef struct QNode
{struct QNode* next;QDataType data;}QNode;typedef struct Queue
{QNode*head;QNode*tail;int szie;
}Queue;//单链表的实现,FIFO//初始化
void QueueInit(Queue* ps);
//销毁
void QueueDestroy(Queue* ps);
//入队
void QueuePush(Queue* ps, QDataType x);
//删除
void QueuePop(Queue* ps);
//大小
int QueueSize(Queue* ps);
//判空队
bool QueueEmpty(Queue* ps);
//出队头
QDataType QueueTop(Queue* ps);
//出队尾
QDataType QueueBack(Queue* ps);

travelling_binary_tree

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
#include <stdlib.h>
#include <assert.h>#include "queue.h"//定义结构体typedef int BTTypeData;typedef struct BinaryTree
{BTTypeData data;struct BinaryTree* left;struct BinaryTree* right;
}BinaryTree;//创建空间BinaryTree* BuyBinaryTree(BTTypeData x)
{BinaryTree* node = (BinaryTree*)malloc(sizeof(BinaryTree));if (node == NULL){perror("malloc fail");return NULL;}node->data = x;node->left = NULL;node->right = NULL;return node;
}//建树BinaryTree* CreateBinaryTree()
{BinaryTree* node1 = BuyBinaryTree(1);BinaryTree* node2 = BuyBinaryTree(2);BinaryTree* node3 = BuyBinaryTree(3);BinaryTree* node4 = BuyBinaryTree(4);BinaryTree* node5 = BuyBinaryTree(5);BinaryTree* node6 = BuyBinaryTree(6);BinaryTree* node7 = BuyBinaryTree(7);BinaryTree* node8 = BuyBinaryTree(8);BinaryTree* node9 = BuyBinaryTree(9);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;node3->right = node7;node6->left = node8;node6->right = node9;return node1;
}//前序遍历
void PreOrder(BinaryTree* root)
{if (root == NULL){//printf("NULL ");return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);
}//中序遍历void InOrder(BinaryTree* root)
{if (root == NULL){//printf("NULL ");return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);}//后序遍历
void PostOrder(BinaryTree* root)
{if (root == NULL){//printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);}//层序遍历void LevelOrder(BinaryTree* root)
{if (root == NULL){printf("NULL ");return;}Queue TBT;QueueInit(&TBT);if (root)QueuePush(&TBT, root);while (!QueueEmpty(&TBT)){BinaryTree* front = QueueTop(&TBT);QueuePop(&TBT);printf("%d ", front->data);if (front->left)QueuePush(&TBT, front->left);if (front->right)QueuePush(&TBT, front->right);}QueueDestroy(&TBT);}//树的结点个数int TreeSize(BinaryTree* root)
{return root == 0 ? 0:TreeSize(root->left) + TreeSize(root->right) + 1;}//树的高度int TreeHeight(BinaryTree* root)
{if (root == NULL){return 0;}int left = TreeHeight(root->left) ;int right = TreeHeight(root->right);return left > right ? left + 1 : right + 1;}//层的个数int TreeKLevel(BinaryTree* root, int k)
{if (root == NULL){return 0;}if (k == 1){return 1;}return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);}//查找节点BinaryTree* TreeFind(BinaryTree* root, BTTypeData x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BinaryTree* lret = TreeFind(root->left, 7);if (lret)return lret;BinaryTree* rret = TreeFind(root->right, 7);if (rret)return rret;return NULL;
}int main()
{BinaryTree* root = CreateBinaryTree();PreOrder(root);printf("\n");InOrder(root);printf("\n");PostOrder(root);printf("\n");LevelOrder(root);printf("\n");printf("TreeSize : %d\n", TreeSize(root));printf("TreeHeight : %d\n", TreeHeight(root));printf("TreeKLevel : %d\n", TreeKLevel(root, 3));printf("TreeFind : %p\n", TreeFind(root, 1));return 0; 
}

}

//查找节点

BinaryTree* TreeFind(BinaryTree* root, BTTypeData x)
{

if (root == NULL)
{return NULL;
}if (root->data == x)
{return root;
}BinaryTree* lret = TreeFind(root->left, 7);
if (lret)return lret;
BinaryTree* rret = TreeFind(root->right, 7);
if (rret)return rret;
return NULL;

}

int main()
{
BinaryTree* root = CreateBinaryTree();

PreOrder(root);
printf("\n");
InOrder(root);
printf("\n");
PostOrder(root);
printf("\n");
LevelOrder(root);
printf("\n");printf("TreeSize : %d\n", TreeSize(root));printf("TreeHeight : %d\n", TreeHeight(root));printf("TreeKLevel : %d\n", TreeKLevel(root, 3));printf("TreeFind : %p\n", TreeFind(root, 1));return 0; 

}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/27662.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#.Net筑基-类型系统①基础

C#.Net的BCL提供了丰富的类型&#xff0c;最基础的是值类型、引用类型&#xff0c;而他们的共同&#xff08;隐私&#xff09;祖先是 System.Object&#xff08;万物之源&#xff09;&#xff0c;所以任何类型都可以转换为Object。 01、数据类型汇总 C#.NET 类型结构总结如下图…

项目采购管理

目录 1.概述 2.三个子过程 2.1.规划采购管理 2.2.实施采购 2.3.控制采购 2.4.归属过程组 3.应用场景 3.1.十个应用场景 3.2.软件开发项目 3.2.1. 需求识别和分析 3.2.2. 制定采购计划 3.2.3. 发布采购请求 3.2.4. 供应商评估与选择 3.2.5. 合同签订 3.2.6. 采购…

Unity动态添加聊天文本

1.创建一个滚动视图 2.调整滚动视图的位置并删掉这个 3.创建一个输入框和一个按钮 这里插一句一定要给content添加这个组件并设置单元格大小 4创建一个脚本并编写下面代码 using System.Collections; using System.Collections.Generic; using TMPro; using Unity.VisualScrip…

YouTube583美元账户做到一千多万美元,125万粉的顶级交易员

油管125万粉丝的Ross Cameron,一位把583美元账户做到一千多万美元。他说他曾经也是像无头苍蝇一样交易,最终凄惨爆仓,也就是在爆仓之后,他终于开始沉下心来研究交易策略,终于终于,他有一天找到了交易模型,并用它执行至今。 Ross Cameron无疑是最成功的日内交易员之一,而…

The Google File System 论文阅读

2003年USENIX&#xff0c;出自谷歌&#xff0c;开启分布式大数据时代的三篇论文之一 总体设计 假设 硬件损坏是常态&#xff0c;而非意外。例如磁盘损坏&#xff0c;断电&#xff0c;断网。所以持续的监控&#xff0c;错误诊断&#xff0c;错误恢复要纳入系统设计之中文件很…

【文档智能 RAG】RAG增强之路-智能文档解析关键技术难点及PDF解析工具PDFlux

前言 在私域知识问答和企业知识工程领域&#xff0c;结合Retrieval-Augmented Generation&#xff08;RAG&#xff09;模型和大型语言模型&#xff08;LLM&#xff09;已成为主流方法。然而&#xff0c;企业中存在着大量的PDF文件&#xff0c;PDF解析的低准确性显著影响了基于…

open-amv开发环境搭建

open-amv是基于rv1103主控芯片的视觉开发板子 1.板子使用 板子使用type c作为调试口&#xff0c;同时供电&#xff0c;请在电脑上下载adb&#xff0c;当板子通过tpye c与电脑连接后&#xff0c;执行命令adb shell就会进入到板子的linux系统命令行。 2.编译环境 2.1 搭建doc…

ipad协议已更新

mmtls 24算法&#xff0c;by golang 其他/v1/other POST/v1/other/GetPeopleNearby 查看附近的人 POST/v1/other/GetQrCode 获取二维码 同步消息/v1/ws GET/v1/ws/GetSyncMsg 同步消息&#xff0c;ws协议 消息/v1/message POST/v1/message/AddMessageMgr 添加要发送…

什么是无杂散动态范围 (SFDR)?为什么 SFDR 很重要?

有多种不同的规格可用于表征电路线性度。SFDR 指标是一种常用的规范。该指标定义为所需信号幅度与感兴趣带宽内杂散的比率&#xff08;图 1&#xff09;。 图 1. 显示 SFDR 指标的图表。 对于 ADC&#xff0c;SFDR 展示了 ADC 如何在存在大信号的情况下同时处理小信号。作为一个…

如何阅读?从阅读中学阅读—《海绵阅读法》

大家好&#xff0c;我是老三&#xff0c;最近读了《海绵阅读法&#xff1a;如何吸收一本书的精华》&#xff0c;第一次阅读教如何阅读的书&#xff0c;整理一番读书笔记&#xff0c;分享给大家。 读书动机 我前一阵子写了篇文章&#xff0c;2024Q1&#xff0c;盘点我看过的54本…

[Java基本语法] 逻辑控制与方法

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;线程与…

一键解锁创意无界:高效AI生成古典肖像图片,轻松打造艺术化身

在数字化时代&#xff0c;创意与艺术的结合正逐渐改变我们的生活。你是否曾梦想过拥有一幅专属于自己的古典肖像画&#xff0c;却又苦于找不到合适的画师或高昂的费用而望而却步&#xff1f;现在&#xff0c;这一切都将成为现实&#xff01; 进入首助编辑高手的AI魔法智绘图板块…

你能不能手敲出Spring框架?

Spring最成功的地方在于创始人Rod Johnson提出的IOC、AOP核心理念&#xff0c;反而不是其本身的技术。技术上今天可以有Spring春天&#xff0c;明天就可以有Autumn秋天。 核心理念有多重要&#xff1f;就如1871年巴黎公社的失败。公社在对抗法国zf和普鲁士占领军的背景下成立&…

英伟达开源 3400 亿巨兽:98% 合成数据训出最强开源通用模型,性能对标 GPT-4o

NVIDIA 最近开源了其大型语言模型 Nemotron-4 340B&#xff0c;这是一个具有划时代意义的模型&#xff0c;它使用了高达 98% 的合成数据进行训练&#xff0c;并且在性能上与 GPT-4 相当。Nemotron-4 340B 包括基础模型、指令模型和奖励模型&#xff0c;支持 4K 上下文窗口、50 …

回答网友的一个Delphi问题

网友想在grid 中 加一个水印&#xff0c;俺就给他写了个例子。先靠效果&#xff1a; 这个例子 包含下面几步&#xff1a; 1、创建背景 dg_bmp:Tbitmap.Create; w: Image1.Picture.Bitmap.width; h: Image1.Picture.Bitmap.height; dg_bmp.width: w*2; dg_bmp.height: …

从入门到高手的99个python案例(2)

51. 列表和数组比较 - 列表通用&#xff0c;NumPy数组高效。 import numpy as np normal_list [1, 2, 3] np_array np.array([1, 2, 3]) print(np_array.shape) # 输出 (3,), 数组有形状信息 52. Python的内置模块datetime - 处理日期和时间。 from datetime import…

数据库MySQL——从0到1入门教程

Q:为什么需要MySQL&#xff1f; A:网络服务中&#xff0c;我们需要存储、管理大量的数据&#xff0c;并确保数据的安全、实现增删改查操作的高效&#xff0c;因此需要一个系统用来专门管理数据&#xff0c;以实现上述的高性能要求&#xff0c;数据库管理系统应需而生 八股如下…

自动化数据驱动?最全接口自动化测试yaml数据驱动实战

前言 我们在做自动化测试的时候&#xff0c;通常会把配置信息和测试数据存储到特定的文件中&#xff0c;以实现数据和脚本的分离&#xff0c;从而提高代码的易读性和可维护性&#xff0c;便于后期优化。 而配置文件的形式更是多种多样&#xff0c;比如&#xff1a;ini、yaml、…

pdf structuredClone is not defined 解决

问题 部分手机系统的浏览器 pdf v2版本会出现 structuredclone is not defined 的报错&#xff0c;这是因为浏览器过低 解决 查看structuredClone的浏览器兼容性 structuredClone api 文档 polyfill 网站下方有个 polyfill的网址入口 可以解决低版本的兼容问题 相应网址…

笨蛋学算法之LeetCodeHot100_3_最长连续序列(Java)

package com.lsy.leetcodehot100;import java.util.Arrays; import java.util.HashSet; import java.util.Set;public class _Hot3_最长连续序列 {public static int longestConsecutive(int[] nums) {//创建set去重//对重复的数字进行去重Set<Integer> set new HashSet…