数据结构06树和二叉树

第六章 树和二叉树

6.1 树的定义和基本术语

树 Tree 是n个结点的有限集。

任意一棵非空树中:

(1)有且仅有一个特定的称为根(root)的结点;

(2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,...,Tm,其中,每一个集合本身又是一棵树,并且称为根的子树(SubTree)。

 

结点:包含一个数据元素及若干指向其子树的分支。

结点的度(degree):结点拥有的子树数。

叶子(Leaf)/终端结点:度为0的结点。

分支结点/非终端结点:度不为0的结点。 除根结点外,分支结点也称为内部结点。

孩子(Child):结点的子树的根称为该结点的孩子。

双亲(Parent):该结点称为孩子的双亲。

兄弟(Sibling):同一个双亲的孩子之间互称兄弟。

祖先:从根到该结点所经的所有结点。

子孙:以某结点为根的子树中的任一结点。

层次(Level):根为第一层,根的孩子为第二层。

若某结点在第l层,则其子树的根在第l+1层。

其双亲在同一层的结点互为堂兄弟

深度(Depth)/高度:树中结点的最大层次。

 

有序树:树中结点的各子树从左至右是有次序的。

无序树:树中结点的各子树从左至右是无次序的。

森林(Forest):m棵互不相交的树的集合。

对树中每个结点而言,其子树的集合即为森林。

 

6.2 二叉树

二叉树 Binary Tree

每个结点至多只有两棵子树,并且二叉树的子树有左右之分,其次序不能任意颠倒。

 

二叉树的5种基本形态:

空二叉树

仅有根节点

右子树为空

左子树为空

左右子树均非空

 

二叉树的性质:

1、在二叉树第i层上至多有2^(i-1)个结点。

2、深度为k的二叉树至多有2^k-1个结点。

3、对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1

结点:n=n0+n1+n2

入度:n=n1+2n2+1

 

 

满二叉树:一棵深度为k且有2^k-1个结点的二叉树称为满二叉树。

特点:每一层上的结点数都是最大结点数。

可以对满二叉树的结点进行连续编号,约定编号从根结点起,自上而下,自左至右。

 

由此可引出完全二叉树的定义:

深度为k的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中的编号从1至n的结点一一对应时,称之为完全二叉树。

特点:

(1)叶子结点只可能在层次最大的两层上出现;

(2)对任一结点,若其右分支下的子孙的最大层次为l,则其左分支下的子孙的最大层次必为l或l+1。

 

完全二叉树的两个重要性质:

1、具有n个结点的完全二叉树的深度为

2、对于完全二叉树的编号:

(1)如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲结点是i/2;

(2)如果2i>n,则i结点无左孩子;否则,其左孩子为2i;

(3)如果2i+1>n,则i结点无右孩子;否则,其右孩子为2i+1。

 

 

二叉树的存储结构:

(1)顺序存储结构:完全二叉树。

(2)链式存储结构:

二叉链表:左孩子、右孩子

三叉链表:左孩子、右孩子、父结点

 

二叉链表存储结构的许多基本操作都采用了递归函数,因为二叉树的层数是不定的,正确采用递归函数可简化编程。
递归函数特点:1、降阶;2、出口。

 

 

在含有n个结点的二叉链表中有n+1个空链域。

可以利用这些空链域存储其他有用信息,从而得到另一种链式存储结构——线索链表

 

6.3 遍历二叉树和线索二叉树

6.3.1 遍历二叉树

将非线性的二叉树结构线性化。

Traversing binary tree

二叉树是由三个基本单元组成:根节点、左子树、右子树

限定先左后右,有三种遍历方式:先序遍历、中序遍历、后续遍历

对二叉树做中序遍历和先序遍历(或者中序遍历和后续遍历),就可以确定二叉树的形状。

 

先序遍历二叉树:

若二叉树为空,则空操作;否则

1、访问根节点;

2、先序遍历左子树;

3、先序遍历右子树。

 

中序遍历二叉树:

若二叉树为空,则空操作;否则

1、中序遍历左子树;

2、访问根节点;

3、中序遍历右子树。

 

后序遍历二叉树:

若二叉树为空,则空操作;否则

1、后序遍历左子树;

2、后序遍历右子树;

3、访问根节点。

 

非递归中序遍历二叉树

 

 

 

二叉树表达式:

前缀表达式-波兰式

中缀表达式

后缀表达式-逆波兰式

 

还可以从上到下,从左到右按层次进行遍历。即层序遍历。

时间复杂度O(n)

空间复杂度O(n)

 

链式结构先序构造二叉树时,要把度数为1的结点和叶子结点的无用指针置空。

 

 

6.3.2 线索二叉树

遍历二叉树是以一定规则将二叉树中结点排列成一个线性序列,得到二叉树中结点的先序序列或中序序列或后序序列。即对一个非线性结构进行线性化操作。

在有n个结点的二叉链表中必定存在n+1个空链域。

利用这些空链域来存储结点的前驱和后继信息。

规定如下:

若结点有左子树,则lchild指向其左孩子,否则,指向其前驱;

若结点有右子树,则rchild指向其右孩子,否则,指向其后继。

 

增加两个标志域:LTag  RTag   0(Link)指向左右孩子,1(Tread)指向前驱后继。

指向前驱和后继的指针,叫做线索

线索二叉树(Threaded Binary Tree)

 

对二叉树以某种次序遍历使其变为线索二叉树的过程叫做线索化

在线索树上进行遍历,只要先找到序列中的第一个结点,然后依次找结点后继直至其后继为空时为止。

 

中序线索树:

后继:

若其右标志为1,右链直接指示后继;

非终端的后继:遍历右子树时,第一个访问的结点为后继,即右子树中最左下的结点。

前驱:

若其左标志为1,左链直接指示前驱;

非终端的前驱:遍历左子树时,最后一个访问的结点为前驱,即左子树中最右下的结点。

 

后序线索树:

后继:

若为根节点,后继为空;

若结点为双亲右孩子,或为左孩子且双亲无右孩子,则其后继为双亲;

若结点为左孩子且双亲有右孩子,则后继为双亲右子树上按后序遍历列出的第一个结点。

在后序线索化树上找后继时需知道结点双亲,即需带标志域的三叉链表作为存储结构。

 

 

中序线索二叉树的遍历,虽然时间复杂度为O(n),但常数因子要小于普通二叉树。

若某程序对二叉树需经常遍历,或查找结点的前驱或后继,应采用线索链表作存储结构。

 

可以在二叉树的线索表上添加一个头结点,令其lchild指向二叉树根结点,rchild指向中序遍历时访问的最后一个结点;令二叉树中序序列中的第一个结点的lchild域指针和组后一个结点rchild域指针指向头结点。

 

线索化的实质是将二叉树链表中的空指针改为指向前驱或后继的线索。

线索化的过程即为在遍历的过程中修改空指针的过程。

附设一个指针pre始终指向前一个访问的结点,指针p指向当前访问结点。

指针pre指向的是p的前驱,指针p指向的是pre的后继。

 

6.4 树和森林

6.4.1 树的存储结构

1、双亲表示法

以一组连续空间存储树的结点,同时在每个结点中附设一个指示器指示其双亲结点的位置。

这种表示法利用了每个结点(根结点除外)只有唯一双亲的性质。

求孩子结点时需要遍历整个结构。

 

2、孩子表示法

把每个结点的孩子结点排列起来,看成是一个线性表,以单链表作为存储结构,则n个结点有n个孩子链表(叶子的孩子链表为空表)。

而n个头指针又组成一个线性表,为了便于查找,可采用顺序存储结构。

孩子表示法便于那些涉及孩子的操作。

 

可以把双亲表示法和孩子表示法结合起来,即将双亲表示和孩子链表合在一起。

 

3、 孩子兄弟表示法

二叉链表作为树的存储结构。

结点的两个链域分别指向该结点的第一个孩子结点和下一个兄弟结点。

分别命名为firstchild域和nextsibling域。

任何一棵和树对应的二叉树,其右子树必空。

 

6.4.2 森林与二叉树的转换

把森林中第二棵树的根结点看成是第一棵树的根结点兄弟,可以导出森林和二叉树的对应关系。

 

6.4.3 树和森林的遍历

两种方式:

先根遍历,对应二叉树的先序遍历;

后根遍历,对应二叉树的后序遍历。

 

6.6 哈夫曼树及其应用

6.6.1 最优二叉树(哈夫曼树)

路径:从一个结点到另一个结点之间的分支构成两个结点间的路径。

路径长:路径上的分支数目。

树的路径长度:从树根到每一个叶子结点的路径长度之和。

带权路径长度:路径长度与结点权值的乘积。

树的带权路径长度:所有叶子结点的带权路径长度之和。

假设有n个权值,对应n个叶子结点,带权路径长度WPL最小的二叉树称为最优二叉树哈夫曼树

 

最优二叉树特点:

权值越小的结点,其到根结点的路径越长。

最优二叉树的左右子树是可以互换的,不影响树的带权路径长度。

 

哈夫曼算法:

(1)根据给定的n个权值{W1, W2, ..., Wn}构成n棵二叉树的集合F={T1, T2, ..., Tn},其中每棵二叉树Ti中只用一个带权为Wi的根结点,其左右子树均空;

(2)在F中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且新的二叉树的根结点的权值为左右子树根结点权值之和;

(3)在F中删除这两棵树,并将新的树加入F中;

(4)重复(2)(3),直至只含一棵树为止。

 

6.6.2 哈夫曼编码

若想设计长短不等的编码,必须是任一个字符的编码都不是另一个字符的编码的前缀,这种编码称作前缀编码

 

可以利用二叉树来设计二进制的前缀编码。

约定左分支为0,右分支为1。

从根结点到叶子结点的路径上的分支01串,即为该叶子结点的前缀编码。

 

设计电文总长最短的二进制前缀编码即为

以n种字符出现的频率作权,设计一棵哈夫曼树,由此得到的二进制前缀码便称为哈夫曼编码。

哈夫曼树中没有度为1的结点。(这类树又称为严格/正则二叉树)

则一棵有n个叶子结点的哈夫曼树共有2n-1个结点,可以存储在一个大小为2n-1的一维数组中。

 

 

 

6.7 回溯法与树的遍历

试探与回溯:在约束条件下,先序遍历一颗状态树。

在程序设计问题中,有相当一类求一组解、或求全部解、或求最优解的问题,这类问题不是根据某种确定的计算法则,而是利用试探和回溯(Backtracking)的搜索技术求解。

回溯法是设计递归过程的一种重要方法,它的求解过程实质上是一个先序遍历一棵“状态树”的过程,这棵树不是遍历前预先建立的,而是隐含在遍历过程中,认识到这一点,许多问题就迎刃而解了。

 

很多问题用回溯和试探求解时,描述求解过程的状态树不是一棵满的多叉树。

当试探过程中出现的状态和问题所求解产生矛盾时,不再继续试探下去,这时出现的叶子结点不是问题的解的终结状态。

这类问题的求解过程可看成是在约束条件下进行先序遍历,并在遍历过程中剪去那些不满足条件的分支。

 

八皇后问题:

任何两个棋子不在同一行、同一列、同一斜线。

求所有合法布局的过程即为在上述约束条件下先根遍历状态树的过程。

 

 

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

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

相关文章

CountDownLatch,CyclicBarrier和Semaphore

在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法。以下是本文目录大纲:一.CountDownLatch用法二.CyclicBarrie…

数据结构07排序

第十章内部排序 10.1 概述 排序就是把一组数据按关键字的大小有规律地排列。经过排序的数据更易于查找。 排序前KiKj,且Ki在前: 排序方法是稳定的,若排序后Ki在前; 排序方法是不稳定的,如排序后Kj在前。 分类: 内…

数据结构08查找

第九章 查找 另一种在实际应用中大量使用的数据结构--查找表。 所谓查找,即为在一个含有众多的数据元素的查找表中找出某个“特定的”数据元素。 查找表 search table 是由同一类型的数据元素构成的集合。集合中的数据元素之间存在着完全松散的关系,故…

下载Centos7 64位镜像

下载Centos7 64位镜像 1.打开Centos官网 打开Centos官方网站地址:https://www.centos.org/,点击Get CentOS Now 2.点击Minimal ISO镜像 Minimal ISO镜像,与DVD ISO镜像的差别有很多,这里只说两点 1.Minimal ISO类似于Windows的纯净…

Scala01入门

第1章 可伸展的语言 Scala应用范围广,从编写脚本,到建立大型系统。 运行在标准Java平台上,与Java库无缝交互。 更能发挥力量的地方:建立大型系统或可重用控件的架构。 将面向对象和函数式编程加入到静态类型语言。 在Scala中&a…

Java网络01基本网络概念

协议 Protocol:明确规则 (1)地址格式; (2)数据如何分包; ... TCP/IP四层模型: 应用层 HTTP SMTP POP IMAP 传输层 TCP UDP 网际层 IP 主机网络层 host to host layer 数模、…

Java网络02基本Web概念

URI Uniform Resource Identifier 同一资源标识符 以特定语法标识一个资源的字符串 绝对URI:URI模式模式特有部分 scheme:scheme-specific-part scheme分为: data file本地文件系统 ftp http telnet urn 统一资源名 scheme-specific-part为&am…

解决自建ca认证后浏览器警告

前一篇讲解了基本的建立证书的过程,但是建立后总是会在浏览器那里警告: 此链接不是私密链接 --谷歌浏览器 此证书颁发机构不可信 此证书不是这个网站的 --ie浏览器 总之证书是生成成功了,但是其中的内容填写错误了&a…

Java网络03流

网络程序所做的很大一部分工作只是输入和输出:从一个系统向另一个系统移动数据。 输出流 Java的基本输出流类是java.io.OutputStream: public abstract class OutputStream 这个类提供了写入数据所需的基本方法,包括: public abstract vo…

基于微信小程序开发的仿微信demo

(本文参考自github/liujians,地址:https://github.com/liujians/weApp) 作者声明: 基于微信小程序开发的仿微信demo 整合了ionic的样式库和weui的样式库 使用请查看使用必读! 更新日志请点击这里 目前功能 查看消息 网络请求获取数据(download示例server…

解决idea 中web项目无法正常显示的问题

转载于:https://www.cnblogs.com/nulijiushimeili/p/10575364.html

分享一个前后端分离的web项目(vue+spring boot)

Github地址:https://github.com/smallsnail-wh 前端项目名为wh-web后端项目名为wh-server项目展示地址为我的github pages(https://smallsnail-wh.github.io)用户名:admin,密码admin(第一次启动会比较慢&am…

部署php项目到linux

服务器:39.106.26.67rootBayou2009 数据库:rootbayou2009 项目文件夹路径:/home/www/项目文件夹名称:education.bayou-tech.cn 绑定域名:education.bayou-tech.cn 绑定域名: 用ftp把配置文件下班到windows修…

ZooKeeper安装配置

配置 1、在conf目录下创建一个配置文件zoo.cfg tickTime2000 dataDir.../zookeeper/data dataLogDir.../zookeeper/dataLog clientPort2181 initLimit5 syncLimit2 server.1server1:2888:3888 server.2server2:2888:3888 server.3server3:2888:3888 •tickTime&#…

ionic2开发的仿外卖点餐系统(Ionic2+Angular2

github上的项目源码 Run this Project(运行该项目) first(首先): make sure your computer install ionic 确保你的电脑安装了ionic2,不懂自行百度 second(其次):$ ionic start wechat_restaurant tutorial…

node搭建服务器,写接口,调接口,跨域

刚开始学node,今天做这个也是累死宝宝了,以后可以自己写接口自己用了,再也不用麻烦人家后台人员了,这些年我们欠他们的太多了,说多了都是泪,不多说,往下看吧。。。 服务端项目目录下&#xff1a…

ThreadPoolExcutor 线程池 异常处理 (上篇)

前言 最近看到crossoverJie的一篇文章:一个线程罢工的诡异事件 首先感谢原作者的分享,自己获益匪浅。然后是回想到自己的一次面试经历,面试官提问了线程池中的线程出现了异常该怎样捕获?会导致什么样的问题? 示例代码 …

ionic3 调用本地相册并上传图片

前言在APP中启动相册选择器或者拍照上传图片这些功能是非常常见的。对于Ionic2,我们只能通过cordova插件实现调用原生的功能。下面将简单的封装一个选择相册或拍照上传图片的ImgService服务。具体如下。 Cordova准备下载安装所需的Cordovar插件: Image P…

Mapreduce中maptask过程详解

一、Maptask并行度与决定机制 1.一个job任务的map阶段的并行度默认是由该任务的大小决定的; 2.一个split切分分配一个maprask来并行处理; 3.默认情况下,split切分的大小等于blocksize大小; 4.切片不是mapper类中对单词的切片&…

angularjs 上传

xxx.module.ts模块 import { NgModule} from “angular/core”; import { FileUploadModule } from “ng2-file-upload” ; import { XXXComponent } from “./xxx.component”; NgModule({ imports:[ FileUploadModule ], declarations:[ XXXComponent ,/component…