高级算法日记5:二叉树

来源:互联网 发布:淘宝海外直邮是正品吗 编辑:程序博客网 时间:2024/06/06 02:58

作者:孙相国

邮箱:sunxiangguodut@qq.com

目录

      • 作者孙相国
    • 二叉树很重要
      • 1 考纲分析
      • 2 知识地位
      • 3 实际应用
    • 树的基本概念与性质
      • 1 树的定义
      • 2 树的逻辑表示方法
        • 树形表示法
        • 凹入表示法
        • 广义表表示法
        • 嵌套表示法
      • 3 树的基本术语
        • 节点的度与树的度
        • 分支节点叶子节点孩子节点双亲节点兄弟节点
        • 有序树和无序树
        • 有根树和无根树
        • 满m次树
        • 完全m次树
        • 路径与路径长度
        • 思考题树究竟是不是无向的
      • 4 树的性质
      • 5 树的遍历存储
      • 6 练习题
    • 二叉树的基本概念与性质
      • 1 性质
        • 非空二叉树
        • 完全二叉树
        • 满二叉树
      • 2 存储
      • 3 二叉树树森林转换
      • 4 练习题
    • 二叉树的基本算法
      • 1 二叉树的遍历
        • 先序遍历
        • 中序遍历
      • 2 创建查找求高度
      • 3 二叉树构造定理
      • 4 练习题
    • 线索二叉树
    • 哈夫曼树
      • 1 哈夫曼树的构造
      • 2 性质
      • 3 习题

0. 二叉树很重要

上两次次课复习

dfs,bfs:随机游走方法

0.1 考纲分析

【考查目标】

  1. 理解数据结构的基本概念;掌握数据的逻辑结构、存储结构及其差异以及各种基本操作的实现。
  2. 掌握基本的数据处理原理和方法的基础上,能够对算法进行设计与分析。
  3. 能够选择合适的数据结构和方法进行问题求解;具备采用c或c++语言设计与实现算法的能力。

三、树与二叉树

  (一) 树的基本概念

  (二) 二叉树

    1. 二叉树的定义及其主要特征    2. 二叉树的顺序存储结构和链式存储结构    3. 二叉树的遍历    4. 线索二叉树的基本概念和构造

  (三) 树、森林

1. 树的存储结构2. 森林与二叉树的转换3. 树和森林的遍历

​(四) 树和二叉树的应用

​1. 二叉排序树

  4. 平衡二叉树  5. 哈夫曼(Huffman)树和哈夫曼编码

0.2 知识地位

0.3 实际应用

机器学习算法中的应用:

1,层次聚类(周志华214)

2,决策树(周志华73)

3,knn与kd树

网络生成模型中的应用:《复杂网络理论与应用》175页

1. 树的基本概念与性质

1.1 树的定义

树是由n(n0)个节点组成的有限集合(记为T)。其中,如果n=0,它是一棵空树;如果n>0,这n个节点中有且仅有一个节点作为树的根节点,其余节点可以分为m(m0)个互不相交的有限集合T1,T2,,Tm,其中每一个子集合本身又是一棵符合本定义的树,成为根节点的子树。

这是王道和一般的辅导书的定义。其实这种定义,并没什么卵用。:smile:

下面是相国大人为你总结的树的“定义”:

自由树(即树),是一个连通的,无环的无向图.

done,是不是和优雅?

其中:

树中的任何两个顶点由唯一的简单路径相连.

树是连通的,但是从图中移除任意一条边得到的图均不连通,如果添加任何一条边,均会形成环,边的个数为|V|1.

树的终极定义

如果一个无向简单图G满足以下相互等价的条件之一,那么G是一棵树:
G是没有回路的连通图。
G没有回路,但是在G内添加任意一条边,就会形成一个回路。
G是连通的,但是如果去掉任意一条边,就不再连通。
G是连通的,并且3顶点K3的完全图不是G的子图。
G内的任意两个顶点能被唯一路径所连通。
如果无向简单图G有有限个顶点(设为n个顶点),那么G是一棵树还等价于:
G是连通的,有n − 1条边,并且G没有简单回路。
如果一个无向简单图G中没有简单回路,那么G是森林

一棵树中每两个点之间都有且只有一条路径(指没有重复边的路径)。一颗有N个点的树有N-1条边,也就是连接N个点所需要的最少边数。所以如果去掉树中的一条边,树就会不连通。
如果在一棵树中加入任意的一条边,就会得到有且只有一个环的图。这是因为这条边连接的两个点(或是一个点)中有且只有一条路径,这条路径和新加的边连在一起就是一个环。如果把一个连通图中的多余边全部删除,所构成的树叫做这个图的生成树。
如果要在树中加入一个点,就要加入一条这个点和原有的点相连的边。这条边不会给这棵树增加一个环或者多余的路径。所以每次这样加入一个点,就可以构成一棵树。
一棵树既可以是有向的也可以是无向的。显然,树是连通图,但不会是双连通图(对于无向图)或者强连通图(对于有向图)。树可以算是稀疏图。
显然树中也没有自环和重复边。

既然开篇的递归式定义没什么卵用,为什么大多数教材都采用了这种定义呢?

别急,后面告诉你答案。

1.2 树的逻辑表示方法

树形表示法

这里写图片描述

凹入表示法

这里写图片描述

广义表表示法

又叫做括号表示法

(A(B(E,F,G),C(H),D(I,J)))

嵌套表示法

又叫做文氏图表示法

这里写图片描述2. 二叉树的概念与性质

1.3 树的基本术语

节点的度与树的度

树中某个节点的子树的个数叫做这个节点的度。树中各个节点的度数最大值叫做树的度,通常讲度数为m的树称为m次树。

请注意!图当中顶点的度数

习惯上,我们喜欢把有根树这个范畴下的点叫做节点,把图这个范畴下的点叫做顶点。

分支节点,叶子节点,孩子节点,双亲节点,兄弟节点

有序树和无序树

若树中各节点的子树是按照一定的次序从左向右安排的,且相对次序是不能随意变换的,则称为有序树(有的人也叫做有向树),否则称为无序树(有的人也叫做无向树)。通常意义上的树都指的是无序树。

有根树和无根树

指定一个节点作为根,叫做有根树。

没有指定根节点的树,叫做无根树。由于无根树没有根节点,因此也没有办法计算树的层次和高度。通常意义上的树都指的是有根树。

满m次树

如果除根节点和叶子节点外,其他节点的度均为m,且所有叶子节点均在同一层,这样的树称为满m次树。对于高度为h的满m次树,节点编号范围为1:mh1m1

完全m次树

对于高度为h的满m次树,按照满m次树的层序编号后,最高层连续缺少编号最大的若干个节点,但最高层中至少有一个节点,这样的树称为高度为h的完全m次树。

路径与路径长度:

对于任意两个节点ki,kj,若树中存在一个节点序列ki,ki1,ki2,,kin,kj,使得序列中除ki之外任意一个节点都是其在序列中的前一个节点的后继,则称该节点序列为由kikj的一条路径,用路径所通过的节点序列ki,ki1,ki2,,kin,kj表示这条路径。路径的长度等于路径所通过的边的数目。

思考题:树究竟是不是无向的?

举例子:

DFS-Tree中,尽管对于有向图,我们的边是有向边,但是得到的DFS-Tree并没有画箭头,因为这里面的方向只能是单向。如果是无向图,那么方向无所谓,得到的DFS-Tree也不需要画箭头。因此树这个图,边是没有箭头的(如果你遇见了待箭头的画法,那是不规范的),因此树是无向图。

我们之所以会听到树”有向“之类的话,是因为树可以表达有向的概念:

首先,树有自由树和有序树(也有人称之为无向树和有向树)的区分。自由树指的是任意节点的孩子之间没有顺序,有序树指的是任意节点的孩子之间有顺序。例如二叉树(A(B,C))与(A(C,B))是两个树。

其次,在有根树中,所有的边是有方向的(尽管没有画箭头),如果<a,b>是树中的一条边,则a是b的双亲节点,b是a的孩子节点。两个兄弟节点之间不存在路径,从根节点到树中其他任何节点都存在路径。

事实上,正是由于树这种有向和无向概念上的“操蛋”,因 此大多数教材中,对树的定义都采用开篇介绍的递归式定义。

1.4 树的性质

n=n0+n1++nm(1.4.1)

Degree=n1=n1+2n2++mnm(1.4.2)

由上面两个式子得到:

n=n1+2n2++mnm+1=n0+n1++nm(1.4.3)

即,树中节点数等于所有节点的度数加1
n0=n2++(m1)nm+1(1.4.4)

除此之外,还有如下的性质:

  • m次树第i层上最多有mi1个节点
  • 高度为h的m次树最多有mh1m1
  • 具有n个节点的m次树最小高度是logm(n(m1)+1)

Why?Because:

nmh1m1,从而mhn(m1)+1,从而hlogm(n(m1)+1)从而hlogm(n(m1)+1)

下面我们来复习一下在图的背景中,相关概念的计算:

1.5 树的遍历,存储

这部分的内容树并不重要,重点考察的是图和二叉树。因此这里了解即可。

树的便利:先根遍历,后根遍历,层次遍历

树的存储:双亲存储,孩子链存储,具体见windows lenovo idear pad上的ppt课件

空间利用率是多少?

1.6 练习题

一共15道题,

一次性让他全部做完,然后再带着他一道题一道题过一遍

7-1-5 一棵高度为h的满m次树中,节点总数为_ _ _ _ _ _

7-1-6 假定一棵度为3的树中节点总数为50,则其最小高度为:

7-1-7 若一棵3次树中有2个度为3的节点,1个度为2的节点,2个度为1的节点,该树一共有( )个节点

7-1-9 若一棵度为7的树有7个度为2的节点,6个度为3的节点,5个度为4的节点,4个度为5的节点,3个度为6的节点,2个度为7度节点,该树一共有( )个叶子节点。

7-1-10 若一棵有n个节点的二叉树,其中分支节点度均为k,则该树中的叶子节点个数是( )

7-1-11 树中任意节点可以有( )个孩子节点,除根节点外,其余节点可以有( )个双亲节点

7-1-13 若一棵树的括号表达式为A(B(E,F),C(G(H,I,J,K),L),D(M(N))) 则该树的度为( ),树的深度为( ),树中叶子结点个数为( )

注意:括号表达式中,括号的个数=分支节点的个数

7-1-14 在有n(n>1)个节点的各棵树其中,高度最小的是( ),共有( )个叶子节点,( )其中高度最大的是( ),共有( )个叶子节点。

7-1-15 判断对错

  • 树中元素之间是多对多点关系
  • 树适合表示层次关系
  • 树和二叉树是两种不同的树形结构
  • 一棵n节点的树中,分支数为n
  • 对一棵树进行先根遍历和后根遍历时,其中叶子节点出现的相对次序是相同的

FTTFT

7-1-16 一棵树的括号表达式为A(B,C(E,F(G)),D) 则:

  1. 这棵树的根节点是
  2. 这棵树的叶子节点是
  3. C的度是
  4. 这棵树的深度是
  5. 节点C的孩子节点是
  6. 节点C的双亲节点是
  7. 顶点F的度是

注意第7个问,问的是顶点,不是节点!

7-1-17 若一棵度为4度树中度为1,2,3,4的节点个数分别是4,3,2,2,则该树叶子节点的个数是多少?总结点个数?

7-1-18 一棵度为m的树中有n1个度为1的节点,n2个度为2的节点,,nm个度为m的节点,问叶子节点个数?

7-1-19 一棵树度为4,度为i的节点个数为i个(i>0),则该树中有多少个叶子节点?

7-1-20 对于具有n个节点的m次树:

  • 若采用孩子链存储结构,共有多少个空指针域?
  • 若采用孩子兄弟链存储结构,共有多少个空指针域?

7-1-21 有n个叶子节点的3次树的最小高度是多少?

7-1-23 一棵高度为h的完全k次树,如果按层次自顶向下,同一层自左向右,顺序从1开始对全部节点进行编号,则:

  1. 最多有多少个节点,最少多少个节点?
  2. 编号为q的节点的第i个孩子节点如果存在,编号是?
  3. 编号为q的节点的双亲节点编号是?

2. 二叉树的基本概念与性质

基本概念:略

2.1 性质

非空二叉树

“三兄弟”

  • n0=n2+1
  • n=n0+n1+n2
  • Degree=n1=n1+2n2

“俩大头”

  • i层上最多有2i1个节点
  • 高度为h的二叉树最多有2h1个节点

n个节点构成的二叉树共有Cn2nn+1

完全二叉树

对于编号为i的节点

  • in/2,即2in,则节点i为分支节点,否则为叶子节点
  • n为奇数,则每个分支节点既有左孩子,又有右孩子。反之,则编号最大的分支节点(n/2)只有左孩子,没有右孩子,其余分支节点都有左右孩子。
  • 完全二叉树中度为1的节点只有0个或1个。

如何找到核心记忆法?

大家好,我是小i,我爸,我妈都叫i/2,我的孩子是2i,2i+1

在完全二叉树中,一旦n确定了,树的形状也就确定了。其中n1=0,or,1,想一想,什么时候取0,什么时候取1?

另外,h=log2nh=log2(n+1).想一想,这是怎么来的?

满二叉树

满二叉树是特殊的完全二叉树

hn0n1n2n=log2(n+1)=2h1=0=2h11=2h1

2.2 存储

略,书231,232

2.3 二叉树·树·森林转换

直接上习题230

森林2二叉树:断父子,连兄弟

  • 当一棵树转换成二叉树后,左分支仍表示原来的父子关系,而右分支表示原来的兄弟关系。
  • 树中有n个分支节点,则二叉树中有n+1个无右节点。

二叉树2森林:断右边,连boss

  • 当一棵二叉树还原为森林时,二叉树中根节点有k个右下节点,则森林中有k+1棵树,

2.4 练习题

27道题

PART ONE 20

7-2-1 以下说法正确的是:

A, 二叉树中每个节点度均为2

B,二叉树中至少有一个节点的度为2

C,二叉树中每个节点的度可以小于2

D,二叉树中至少有一个节点

7-2-2 按照二叉树的定义,具有3个节点的二叉树有( )中

7-2-4 具有10个叶子节点的二叉树中有( )个度为2的节点

7-2-6 一棵二叉树有35个节点,其中所有节点的度之和( )

7-2-7 深度为5的二叉树最多有( )个节点

7-2-10 一个具有1025个节点的二叉树高( )

7-2-12,13 设高度为h的二叉树只有度为0和2的节点,则此类二叉树中所包含的节点数至少是( ),最多是( )

注意:这个二叉树已定是满二叉树吗?一定是完全二叉树吗?

7-2-14 一棵完全二叉树中有1001个节点,其中叶子节点个数是( )

7-2-15,16 一棵完全二叉树中有501个叶子节点,则至少有( )个节点。最多( )个节点。

7-2-17 一棵高度为h的完全二叉树至少有( )个节点

7-2-20 一棵满二叉树有m个叶子节点和n个节点,其深度为h,则有( )

A n=h+m

B h+m=2n

C m=h1

D n=2h1

答题技巧

在完全二叉树中,一旦n确定了,树的形状也就确定了,因此直接排出A,B,又因为C是线性关系,一定错误,所以选D

7-2-21 一棵满二叉树中有127个节点,其中叶子节点个数是( )

7-2-25 二叉树A(B(C(,D)),E(F(,G),H(I,J))),是由森林转换的来的,那么森林有( )个叶子节点

7-2-26 设森林中有3棵树,第1,2,3棵树的节点个数分别是9,8,7,则森林对应的二叉树根节点的右子树上的节点个数是( )

7-2-27 设森林对应的二叉树有m个节点,其根节点的右子树节点个数为n,则森林中第一棵树的节点个数是( )

7-2-28 设森林中有n个非终端节点,则转换的二叉树中无右孩子节点个数为( )

7-2-30 在一棵完全二叉树中,编号i和编号j的两个节点处于同一层的条件是( )

7-2-31 在一棵总结点数为偶数的完全二叉树中,叶子节点个数为k,最后一层节点数大于2,则该二叉树的高度为( )

7-2-33 高度为h的完全二叉树至少有( )个节点,最多有( )个节点,第h层中编号最小的叶子节点的编号( )

7-2-35 在具有n个节点的二叉树中如果有m个叶子节点,则一定有( )度为1的节点,( )度为2的节点

PART TWO 7

7-2-38,39判断正误

  • n(n>2)个节点的二叉树中至少有一个度为2的节点
  • 不存在这样的二叉树:n个度为0的节点,n-1个度为1的节点,n-2个度为2的节点。
  • 在任何一棵完全二叉树中,叶子节点或者和分支节点一样多,或者只比分支节点多一个
  • 完全二叉树中的每个节点或者没有孩子或者有两个孩子
  • 二叉树就是度为2的树
  • 将一棵含有两个以上节点的树转换成二叉树后,该二叉树的根节点没有左子树。
  • 一棵满二叉树中每棵子树也是满二叉树
  • 一棵满二叉树中每棵子树也是完全二叉树
  • 二叉树是一种特殊的树
  • 完全二叉树最适合顺序存储结构

FTTFFF TTFT

7-2-45 一棵完全二叉树的第6层有8个节点,则该完全二叉树的节点个数最多有( )个,最少有( )个。

7-2-46 判断对错:一棵完全二叉树,知道叶子节点个数,就可以确定其形状

F

7-2-46 一棵完全二叉树有50个叶子节点,则该二叉树的总节点数至少有多少个?

7-2-47 已知一棵完全二叉树有892个节点,试求:

  • 树的高度
  • 单支节点个数
  • 叶子节点个数
  • 最小的叶子节点编号

7-2-48 高度为8的完全二叉树第8层有8个节点,则其叶子节点个数

7-2-51 一棵满二叉树节点个数为20-40之间的素数,次二叉树的叶子节点有多少个?

3. 二叉树的基本算法

3.1 二叉树的遍历

先序遍历

pre_order(root):    if root == None:        return    else:        visit(root)        pre_order(root.left_child)        pre_order(root.right_child)
def pre_order(root):  stack.push(root)  while not stack.empty():    u=stack.pop()    visit(u)    if u.right_child != None:      stack.push(u.right_child)    if u.left_child != None:      stack.push(u.right_child)

中序遍历

mid_order(root):  if root != None:    mid_order(root.left_child)    visit(root)    mid_order(root.right_child)

扫描root左孩子节点,进栈
弹出栈顶元素,访问
扫描刚才弹出的元素的右孩子节点,进栈,
扫描这个节点的左孩子节点

mid_order_stack(root):  current=root  while not stack.empty():    stack.push(current)    while(current.left_child!=None):      stack.push(current.left_child)      current=current.left_child    current=stack.pop()    visit(current)    current=current.right_child

后序遍历

post_order(root):  if root!=None:    post_order(root.left_child)    post_order(root.right_child)    visit(root)

家庭作业:自己回去,完成后序遍历的栈的实现

提示:后续遍历中,右孩子节点,一定刚好在father之前访问,后序遍历中最后一个节点一定是根节点

层次遍历

level_order(root):    current=root    queue.push(current)    while not queue.empty():      current=queue.front      visit(current)      queue.pop()      if current.left_child:          queue.push(current.left_child)      if current.right_child:          queue.push(current.right_child)

3.2 创建·查找·求高度

3.3 二叉树构造定理

书249-252

3.4 练习题

20道题

7-3-1 如果二叉树是由一棵树转换而来的,那么这棵树的先根序列对应二叉树的( )序列

7-3-2 如果二叉树是由一棵树转换而来的,那么这棵树的后根序列对应二叉树的( )序列

7-3-3 某二叉树的先序遍历序列和后序遍历序列正好相反,则该二叉树一定

A 空或只有一个节点

B 完全二叉树

C 二叉排序树

D 高度等于其节点数

7-3-4 在一棵非空二叉树的中序遍历序列中,根节点的右边

A 只有右子树的所有节点

B 只有右子树上的部分节点

C 只有左子树上的部分节点

D 只有左子树上的所有节点

7-3-5 任何一棵二叉树的叶子节点在先序,中序,和后序序列中的相对次序

A 不发生改变

B 发生改变

C 不能确定

7-3-6 设n,m为一棵二叉树上的两个节点,在中序序列中,n在m之前的条件是

A n在m右边

B n是m祖先

C n在m左边

D n是m子孙

7-3-7 设n,m为一棵二叉树上的两个节点,在先序序列中n在m之前,在后序序列中n在m之后,则n和m的关系是

A n是m的左兄弟

B n是m的右兄弟

C n是m的祖先

D n是m的子孙

7-3-8 设n,m为一棵二叉树上的两个节点,应该选择( )两个序列来判断n是否是m的祖先

A 先序和后序

B 先序和中序

C 中序和后序

D 以上均可以

7-3-9 对二叉树的节点从1开始编号,要求每个节点的编号大于其左孩子,小于其右孩子,则可以采用()遍历实现二叉树的节点编号

7-3-10 若二叉树采用二叉链存储结构,要交换其所有分支节点的左,右子树中节点的位置,利用()遍历方法最合适

7-3-11 一棵二叉树的先序遍历为ABCDEFG,中序遍历可能是

A: CABDEFG

B: ABCDEFG

C:DACEFBG

D:ADCFEG

7-3-12 一棵二叉树的先序遍历为ABCDEF,中序遍历为DEBAC,则先序遍历序列为

7-3-13 一棵二叉树的后序遍历为DABEC,中序遍历为DEBAC,则先序遍历为

7-3-14 一棵二叉树先序遍历EFHIGJK,中序遍历为HFIEJKG,则该二叉树根节点的右孩子为

7-3-16 二叉树先序序列和中序序列相同的条件为

7-3-17 二叉树后序序列和中序序列相同的条件为

7-3-18 若一棵二叉树叶子节点是某子树中序序列中的最后一个节点,则它必是该子树()序列中的最后一个节点。

7-3-20 判断正误

  • 由二叉树某种遍历方式产生的结果是一个线性序列
  • 给定二叉树的某种遍历结果,对应的二叉树不是唯一的
  • 二叉树的先序遍历病不能为一确定这棵树,但是如果还知道该树的根节点,则可以确定这棵树
  • 用二叉树的先序序列和中序序列可以推导出树的后序序列

TTFT

7-3-24 如果在二叉树节点的先序序列,中序序列和后序序列中,节点a,b的位置是a在前,b在后,则ab可能是兄弟吗?a可能是b的双亲吗?a可能是b的孩子吗?

7-3-25 若已知一棵完全二叉树的某种遍历序列,能够为一确定这棵二叉树吗?

7-3-26 一棵二叉树的先序,中序,后序分别如下,请将空格处的地方补充完整

先序序列:_ B _ F _ ICEH _ G

中序序列:D _ KFIA _ EJC _

后序序列:_ K _ FBHJ _ G _ A

4. 线索二叉树

7-4-1 引入线索二叉树的目的是

A 加快查找节点的前驱或后继

B 为了能在二叉树中方便插入和删除

C 为了能够方便找到双亲

D 是二叉树的遍历结果唯一

7-4-2 线索二叉树是一种()结构

A 逻辑

B 逻辑和存储

C 物理

D 线性

7-4-4 n个节点的线索二叉树上含有的线索数为

7-4-5 一棵线索二叉树中含有的线索数比分支数多()个

7-4-6 二叉树在线索化后,仍然不能有效求解的问题是

A 先序线索二叉树中求先序后继

B 中序线索二叉树中求中序后继

C 中序线索二叉树中求先序前驱

D 后序线索二叉树中求后序后继

先不能先,后不能后

5. 哈夫曼树

5.1 哈夫曼树的构造

5.2 性质

一棵哈夫曼树是一棵二叉树,没有度为1的节点

对于具有n0个叶子节点的哈夫曼树,共有2n01个节点

在同一组哈夫曼编码中,一个字符不可能是其他任何字符的前缀

5.3 习题

7-5-2 根据使用频率为5个字符设计的哈夫曼编码不可能是

A 111,110,10,01,00

B 000,001,010,011,1

C 100,11,10,1,0

D 001,000,01,11,10

7-5-5 有13个值,用它们组成一棵哈夫曼树,则该哈夫曼树共有()个节点

7-5-7 若以{4,5,6,7,8}作为叶子节点的权值构造一棵哈夫曼树,则其带权路径长度为()各个节点的哈夫曼编码为()

7-5-8 判断正误

  • 哈夫曼树中不存在度为1的节点
  • 权值相同的叶子节点都在同一层上
  • 权值较大的叶子节点一般距离根节点较远
  • 哈夫曼树是带权路径长度最小的树,路径上权值较大的节点距离根节点较近

TFFT

7-5-10 设哈夫曼编码长度不超过4,若已经对两个字符编码为1,01,则最多还可以对多少个字符进行编码