第七章解决二叉树的编程问题

第七章      解决二叉树的编程问题

二叉树是n(≥0)个有限元素的集合,该集合或者为空,或者由一个称为根的元素及两个不相交的,被称为左子树和右子树的二叉树组成。当集合为空时,称该二叉树为空二叉树,在二叉树中一个元素也称为一个结点。

二叉树是有序的,即将其左右子树颠倒,就成为另一个不同的二叉树。

结点的,结点所拥有的子树的个数

结点,度为0的结点,也称为终端结点

分支节点,度不为0的结点,也称为非终端结点

孩子、兄弟、双亲结点,树中一个结点的子树的根节点称为这个结点的孩子。这个结点称为孩子的双亲,具有同一个的双亲的孩子结点互称为兄弟结点。

路径、路径长度,如果一棵树的一串结点n1,n2,……,nk有如下关系:结点ni是ni+1的父结点(1≤i≤k),就把n1,n2,……,nk称为一条由n1至nk的路径。这条路径的长度是k-1

祖先、子孙。在树中,如果有一条路径从结点M到结点N,那么M就称为N结点的祖先,而N称为M的子孙。

结点的层数。规定树的根结点的层数为1,其余结点的层数等于它的双亲结点的层数加1。

树的深度。树中所有结点的层数的最大值称为该树的深度。

满二叉树,在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子结点都在同一层上,这样的一棵二叉树称为满二叉树。

完全二叉树,一棵树深度为k的有n个结点的二叉树,对树中的结点按从上至下,从左至右的书序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵树称为完全二叉树。完全二叉树的特点是:叶子结点只能出现在最下层和次下层,且最下层的叶子节点集中在树的左部。显然一棵满二叉树必定是完全二叉树,反之,则不然。

二叉树的性质:

1)  一棵非空二叉树的第i层最多有2i-1个结点(i≥1)

2)  一棵深度为k的二叉树中,最大具有2k-1个结点

3)  对于一棵非空的二叉树,如果叶子结点数为n0,度为2的结点数为n2,则有:

n0=n2+1

4)  具有n个结点的完全二叉树的深度k为[log2n]+1。

5)  对于具有n个结点的完全二叉树,如果按照从上到下和从左到右的顺序对二叉树中的所有结点从1开始进行编号,则对于任意序号为i的结点有:

  • 如果i>1,则序号为i的结点的双亲结点的序号为i/2(整除);如果i=1,则序号为i的结点是根结点,无双亲结点。
  • 如果2i≤n,则序号为i的结点的左孩子结点的序号为2i;如果2i>n,则序号为i的结点无左孩子
  • 如果2i+1≤n,则序号为i的结点的右孩子结点的序号为2i+1;如果2i+1>n,则序号为i的结点无右孩子
  • 此外,若对二叉树的根结点从0开始编号,则相应的i号结点的双亲结点的编号为(i-1)/2,左孩子的编号为2i+1,右孩子的编号为2i+2

二叉树的顺序存储:用一组连续的存储单元存放二叉树中的结点,完全二叉树和满二叉树用顺序存储比较合适

二叉树链式存储:用链表来表示一棵二叉树,即用链表来指示这元素的逻辑关系。

1)  二叉链表存储:数据域、指向左右孩子所在的链结点的存储地址,如下图:

2)  三叉链表存储:最后加一个指向双亲结点的指针域,如下图:

二叉树遍历方法:

1)  先序遍历:

  • 若二叉树为空,遍历结束,否则
  • 访问根结点
  • 先序遍历根结点左子树
  • 先序遍历根结点右子树

2)  中序遍历

  • 若二叉树为空,遍历结束。否则,
  • 中序遍历根结点的左子树
  • 访问根结点
  • 中序遍历根结点右子树

3)  后序遍历

  • 若二叉树为空,遍历结束。否则,
  • 后序遍历根结点的左子树
  • 后序遍历根结点的右子树
  • 访问根结点

4)  层次遍历

从二叉树的第一层(根结点)开始,从上至下逐层遍历,在同一层中,则按从左至右的顺序对结点逐个访问。

基本思想是:由于层次遍历结点的顺序是先遇到的结点先访问,与队列操作的顺序相同。所以,在进行层次遍历时,设置一个队列,将根节点引入队,当队列非空时,循环执行以下三步:

(1)      从队列中取出一个结点引用,并访问该结点

(2)      若该结点的左子树非空,将该结点的左子树引用入队

(3)      若该结点的右子树非空,则将该结点的右子树引用入队

各种遍历算法示例如下:

最优二叉树——哈夫曼树

         最优二叉树,也称哈夫曼树,是指对于一组带有确定权值的叶节点,构造的具有最小带权路径长度的二叉树。

二叉树的路径长度是指由根结点到所有叶节点的路径长度之和

如果二叉树中的叶子结点带有一定的权值,二叉树的路径的长度可以推广为:从根结点到各个叶节点的路径长度与相应叶节点权值的乘积之和(记为WPL)。

构造哈夫曼树的思路:根据哈夫曼树的定义,要使其WPL值最小,必须使权值最大叶结点越远离根结点。

算法描述

1)  给定n个权值{W1,W2…… Wn}构造n棵只有一个叶子结点的二叉树,从而得到一个二叉树的集合F={T1,T2……Tn};

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

3)  在集合F中删除作为左右子树的两棵二叉树,并将新建立的二叉树加入到集合F中;

4)  重复2)、3)两步,当F中只剩下一棵二叉树时,这课二叉树便是所要建立的哈夫曼树。

例子:

时间: 2024-10-18 19:52:32

第七章解决二叉树的编程问题的相关文章

第三章解决堆栈的编程问题

第三章      解决堆栈的编程问题 堆栈是一种特殊的线性表,是一种只允许在表的一端进行插入或删除操作的线性表. 堆栈的主要特点是后进先出. 用一片连续的存储空间来存储栈中的元素,这样的栈称为顺序栈. 用链式存储结构存储的栈称为链栈. 汉诺塔问题 汉诺塔问题来自一个古老的传说:在世界刚刚被创建的时候有一座砖石宝塔(A),其上有64个金蝶.所有按从大到小的顺序从塔底堆放至塔顶.紧挨着这座塔有两个砖石塔(B和C).从世界创始之日起,婆罗门的牧师们就一直在试图把A塔上的碟子移动到B上去,其间借助于C的

第九章 解决图的编程问题

第九章      解决图的编程问题 图的定义: 图是由一系列定点(结点)和描述定点之间的关系边(弧)组成.图是数据元素的集合,这些数据元素被相互连接以形成网络.其形式化定义为: G=(V,E) V={(Vi|Vi∈某个数据元素集合)} E={(Vi,Vj)|Vi+Vj∈V^P(Vi,Vj)} 其中,G表示图:V是顶点集合:E是边或弧的集合.在集合E中,P(Vi,Vj)表示顶点Vi和顶点Vj之间有边或弧相连 相关术语 顶点集:图中具有相同特性的数据元素的集合成为顶点集 边(弧):边是一对顶点间的路

第七章|7.3并发编程|协程

1.协程 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作系统强制控制),一种情况是该任务发生了阻塞,另外一种情况是该任务计算的时间过长或有一个优先级更高的程序替代了它 ps:在介绍进程理论时,提及进程的三种执行状态,而线程才是执行单位,所以也可以将上图理解为线程的三种状态 一:其中第二种情况并不能提升效率,只是为了让cpu能够雨

第七章 资源在Windows编程中的应用 P157 7-8

资源在基于SDK的程序设计中的应用实验 一.实验目的 1.掌握各种资源的应用及资源应用的程序设计方法.   二.实验内容及步骤 实验任务 1.熟悉菜单资源的创建过程: 2.熟悉位图资源的创建: 3.熟悉对话框资源的应用: 4.熟悉图标资源. 实验内容 在一个窗口中央加载一个任意位图,位图尺寸为窗口面积的四分之一,当单击鼠标左键或键盘上的向上箭头时,位图向上移动,当移动到窗口的上边界时,窗口显示"不能再向上移动了"字样,当单击鼠标右键或键盘上的向下箭头时,位图向下移动,当到达窗口的下边界

第四、五章解决队列和串的编程问题

第四章      解决队列的编程问题 队列是一种特殊的线性表,是一种只允许在表的一端进行插入操作而在另一端进行删除操作的线性表.把进行插入操作的表尾称为队尾,进行删除操作的头部称为对头: 队列的主要特点是:先进先出,或后进后出 用一片连续的存储空间来存储队列中的数据元素,这样的队列称为顺序队列. 将顺序队列看成是首位相接的循环结构,这种队列叫做循环队列. 第五章      解决串的编程问题 串即字符串,是由0个或多个字符组成的有限序列,是数据元素为单个字符的特殊线性表. 顺序结构存储串: 串的静

《Programming in Go》第七章并发编程译文

中文译名 Go 编程 外文原文名 Programming in Go 外文原文版出处 the United States on recycled paper at RR Donnelley in Crawfordsville, Indiana. 译 文: 第七章 并发编程 7.1主要概念 7.2例子 7.2.1:过滤器 7.2.2:并发查找 7.2.3:线程安全表 7.2.4:Apache 报告 7.2.5:找重复 并发编程能够让开发者实现并行算法,以及利用多处理器和多核写程序.但是在大多主流变

《Python核心编程》 第七章 映射和集合类型 - 习题

课后习题 7–1. 字典方法.哪个字典方法可以用来把两个字典合并到一起? 答: dict1 = {'1' :' python' } dict2 = {'2' :"hello" } dict1.update(dict2) dictAll = dict1 print dictAll Result: {'1': ' python', '2': 'hello'} 7–2. 字典的键.我们知道字典的值可以是任意的 Python 对象,那字典的键又如何呢?请试 着将除数字和字符串以外的其他不同类型

[书籍翻译] 《JavaScript并发编程》第七章 抽取并发逻辑

本文是我翻译<JavaScript Concurrency>书籍的第七章 抽取并发逻辑,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript并发编程方面的实践. 完整书籍翻译地址:https://github.com/yzsunlei/javascript_concurrency_translation .由于能力有限,肯定存在翻译不清楚甚至翻译错误的地方,欢迎朋友们提issue指出,感谢. 到本书这里,我们已经在代码中明确地模拟了并发问题.使

c++ primer plus(第6版)中文版 第七章编程练习答案

第七章编程练习答案 7.1编写一个程序,用户不停输入两数,直到有0出现为止,计算调和平均数 //7.1编写一个程序,用户不停输入两数,直到有0出现为止,计算调和平均数 #include <iostream> using namespace std; double average (unsigned x, unsigned y) { return (2.0 * x * y / (x + y)); } int main () { while (true) { unsigned x, y; cout