| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 数据结构--树--二叉树的创建和遍历(前序、中序、后序、层序) -> 正文阅读 |
|
[数据结构与算法]数据结构--树--二叉树的创建和遍历(前序、中序、后序、层序) |
1.有关树的定义和基本概念,请阅读:数据结构–树--树的定义和基本概念 2.有关二叉树的定义概念等基本知识,请阅读:数据结构–树--二叉树的定义、基本概念和性质 3.因为我的文字浅显,可能对二叉树的遍历创建过程描述的并不很清楚,又未配有插图,读者可参考网站visualgo中的二叉树部分,观察动画帮助理解。 本章内容:
我们之前已经介绍了树和二叉树的基本概念,那么现在需要做的就是使用代码去实现树这种逻辑结构。所以和前面我们学过的每一种数据结构一样,我们首先要分析二叉树的存储结构,构建它的结构模型,再实现一些基本的操作。 🌳二叉树的存储方式说到存储方式,我们自然而然地能够想到顺序存储结构和链式存储结构。那么二叉树是不是也可以使用这两种存储结构呢?我们分别来看一下。 🔅1.二叉树的顺序存储结构我们先来分析一下树能否使用顺序存储结构。 但是我们来看看二叉树。先来看完全二叉树: 我们来想象一个更极端的场景,如果一棵二叉树是斜树,也就是说,从根结点到叶子结点只有左孩子或者只有右孩子,那么这棵二叉树要用顺序存储结构,就要浪费大量的空间,这显然是不够友好的。 综上所述,对于一棵完全二叉树来说,顺序结构是非常适用的。但是对于一般情况下的二叉树,我们需要寻求一种更节省空间的存储方式,就是我们的链式存储。 🔅2.二叉链表
如下图1.1:
🌳二叉树的创建及初始化如何在内存中使用链式存储结构构建一棵二叉树呢?这似乎有点无从下手。那么我们首先来想一想,如果让一个用户去通过从键盘输入的方式构建一棵二叉树他该输入什么呢?为了搞明白如何输入,我们就要先确定怎么去读这棵二叉树,我们以上图1.1为例,讲讲以何种方式去读取这棵二叉树的元素。其实按照什么顺序去读就是按照什么顺序去遍历。 看到图1.1的这棵二叉树,我们的第一习惯肯定是从根结点A开始读取,然后再去看A的左孩子B,看完B后再看A的右孩子C。这里我们定下一个读取的顺序:先根结点,再左孩子,最后右孩子。 注意,我们这里不能直接先A再B最后C,而是应该从左孩子开始一直读到底。什么意思呢?就是应该读完B再以B为根结点继续向下读B的左孩子,如果B有左孩子就继续以B的左孩子为根结点这样读。这里可能你会想到一点什么?对,就是递归!我们把一整棵二叉树从根结点开始一层层剥离,一层层递归。那么什么时候就不继续剥离了呢?就是读到空之后,比如图1.1中,我们从A读到B了,下一步应该是读B的左孩子,但是发现B没有左孩子,那么B结点的左子树这一边就结束了,开始读B的右孩子D,读到D就开始以D为根结点,读D的左孩子,D也没有左孩子,那就接着读D的右孩子,D也没有右孩子,那D这一个结点就结束了,也标志着根结点A的左半边读完了。程序开始向上返回去读A的右孩子。 这一种先访问根结点的遍历方式就是前序遍历。 对于图1.1,前序遍历的顺序应该是A-B-D-C。 我们前面说,如何让用户在键盘上输入一个他想要构建的二叉树,其实如何输入和如何读取是一模一样的,只不过一个是在遍历时读取,另一个是在遍历时键入。所以这里,我们使用前序遍历的方式创建二叉树。 为了让程序知道何时该返回空值来结束二叉树的分支的键入,我们约定用户如果在该输入这个结点的元素时键入“#”,程序就认为这个结点是个空结点。我们先将图1.1中的二叉树补齐,如图2.1:
针对上面这个代码,我们如果要键入图2.1这棵二叉树,如何键入呢? 具体的实现效果我们看文章最后的例子展示 🌳二叉树的遍历二叉树的遍历( traversing binary tree )是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。 这里有两个关键词:访问和次序。 访问其实是要根据实际的需要来确定具体做什么,比如对每个结点进行相关计算,输出打印等,它算作是一个抽象操作。在这里我们可以简单地假定就是输出结点的数据信息。 二叉树的遍历方式总的来说有这么四种:前序遍历、中序遍历、后序遍历、层序遍历。 🔅1.前序遍历前序遍历我们前面介绍了,就是先访问根结点,然后访问左子树,再访问右子树。
🔅2.中序遍历若树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。
🔅3.后序遍历若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。
🔅4.层序遍历若树为空,则空操作返回,否则从树的第一层, 也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。 那么如何使用这个队列来满足层序遍历的要求呢?我们说有以下的步骤:
访问:A
访问:A
访问:ABC
访问:ABCDE
访问:ABCDEF
访问:ABCDEF
访问:ABCDEFK
访问:ABCDEFK
访问:ABCDEFK 观察上面的步骤,我们发现,每判断一次某个结点的左右子树就要有出队到入队这个循环操作。所以从根结点开始,我们循环判断每一个结点,先让结点出队,再用两个if语句判断左右子树,如果有左右子树就访问后让子树结点入队并出队下一个结点,没有左右子树就直接出队下一个。这是一个循环,循环的终止条件就是队列为空的时候。 代码:
注意,因为我们入队的是一个结点,因此调用我们写过的队列的.h文件时,要将队列中的数据改成二叉树结点类型:
🌳程序测试及效果
测试main函数:
我们再遍历中预测的是不同遍历分别是一下顺序: 看下效果: |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 7:25:08- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |