上篇数据结构系列:树?二叉树?有一说一,这俩货你不会真的不行,我们简单的分享了树结构的一般特点和二叉树结构相关的特性和实现,本篇将基于二叉树分享相关的遍历方法(前序,中序,后序,层序),以及部分应用的算法。
01了解二叉树的遍历
我们知道,线性表的遍历,我们可以通过for循环或者迭代器。而树的遍历,明显不太可能以相同的方式进行,毕竟树结构抽象的是层级结构。
二叉树的遍历从宏观的大角度看,分为深度优先遍历(前序,中序,后序),广度优先遍历(层级),如图
概括地说:深度优先遍历主要包括前序遍历,中序遍历,以及后序遍历,广度优先遍历主要是指层级遍历(每遍历完整层再遍历下一层,这里都是以从左往右的顺序进行元素的遍历)。
对于3种深度优先遍历来讲,最简单的理解方法就是:将当前节点,当前节点的父节点,当前节点的子节点当作一个整体看,分别判断左中右的顺序,这样其实就很好理解。
比如说:中序遍历(左中右的顺序),也就是先从最左边的最左节点开始,然后此子树的中间节点(当前树的根节点),然后此子树的右节点,此时这棵左子树已经遍历完成,把当前遍历完成的左子树看作一个整体,找到这棵树是哪个结点的左子节点,然后遍历此左子节点的中间节点,以此类推。
下面分享这几种不同的遍历方法及实现
02前序遍历(根-gt;左-gt;右)
前序理解
若二叉树为空,则直接返回;否则按照根节点,然后左子树,右子树的顺序依次访问(解释:每访问一个节点,就把当前节点当作根节点,然后找左右子节点,如果有左节点,则把左节点当作当前树的根结点,继续找左右子节点……)
前序实现
03中序遍历(左-gt;根-gt;右)
中序理解
树为空,直接返回;否则就从根节点开始(但并不是以根节点开始访问),找到最最最左子节点开始,然后当前左子节点的父节点,然后右节点,结果如下
中序实现(基于递归)
04后序遍历
后序理解
若树为空,则直接返回;否则先遍历左子树,然后右子树,最后访问根节点,结果如下
后序实现(基于递归)
05层序遍历
层序理解
这个最简单:从每一层开始,按照从左往右的顺序遍历结点
层序实现
说到这,二叉树的几种遍历就差不多结束了,接下来我们分享几个重要的基于二叉树的应用
06堆(heap)
概念
堆排序是高效排序算法的一个解决方案,它的主要优点是,无论输入数据如何,它的最坏情况运行时间都是O(n*logn)。
堆排序是优先队列最主要的实现方法
特点
有这样一个特点(堆次序):任何一条路径都是已经排好序的有序数列
最小堆每个节点的数据项都小于或等于其两个子节点数据,最小的项位于根节点最大堆每个节点的数据项都大于等于其两个子节点的数据,最大的项位于根节点堆结构一般有如下几个接口
heap.is_empty()-堆是否为空堆,返回布尔值heap.heappush(item)-增加数据到堆结构heap.heappop()-返回heap最顶部的数据,并删除heap.peek()-返回heap最顶端的项
我们这里都基于数组实现堆结构,因为对于数组(这里引申为python的列表)来讲,在一个列表中,父节点和子节点的索引存在着一定的关系(如果专门保存一个空元素给列表的第一个位置,那么子节点的索引永远等于父节点地板除2的值)
实现
07表达式树
表达式树是包含了表达式的运算数和运算符的二叉树。这里主要是将中缀表达式转换为解析树结构
大概的思路
将中缀转换为全括号表达式来进行操作,exp:3+5*3-2-((3+(5*3))-2)将所有数据存入列表,准备利用栈结构从左到右扫描全括号表达式的每个单词创建一个空树,当前结点就为根结点如果是(:为当前结点添加一个新的左结点,当前结点下降为这个新结点如果是±*/,将当前结点的值赋值为此符号,同时为当前结点添加一个新结点作为其右子结点,当前结点下降为这个新结点如果当前是操作数,将当前结点的值设为此数,当前结点上升到父结点如果当前结点是),则当前结点上升到父结点具体实现
我是一名奋战在编程界的pythoner,工作中既要和数据打交道,也要和erp系统,web网站保持友好的沟通……时不时的会分享一些提高效率的编程小技巧,在实际应用中遇到的问题以及解决方案,或者源码的阅读等等,欢迎大家一起来讨论!如果觉得写得还不错,欢迎