Mooc数据结构-03树
Posted weihuchao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mooc数据结构-03树相关的知识,希望对你有一定的参考价值。
1 树和树的表示
在客观世界中有许多事物存在层次关系
如: 人类社会的家谱; 社会的组织结构; 图书信息管理等等
分层次组织在管理上有更高的效率
对于信息管理, 常用的操作有增加删除和查询, 在树中查询是重点
关于查找
查找: 根据某个给定的关键字K, 从集合R中找出关键字与K相同的记录
静态查找: 集合中的记录是固定的, 没有插入和删除操作
动态查找: 集合中的记录是动态变化的, 可以查询, 插入和删除
静态查找
方法1:顺序查找
Tb1指向一个存储空间, 有两部分内容, 一个是指向数组, 另一个是表中数据的个数
一般把数组首或者尾作为哨兵, 用于减少一次循环终结的判断
时间复杂度为O(n)
方法2: 二分查找
条件: 元素是有序排列的, 用数组来存储
对N每次除以2直到N变为1, 因而时间复杂度为O(logN)
对于序列1~11, 根据二分查找的提示, 可以形成判定树
判定树上的节点查找到的比较次数刚好是节点所在的层数
查找成功的查找次数 <= 判定树的深度
n个节点的判定树的深度为 [long2n]+1 (向下取整再加1)
平均成功查找次数ASL = (层数*层所在的节点个数)求和/总结点数
ASL = (4*4+4*3+2*2+1)/11=3
1.1 树的定义
树: n个节点构成的有限集合
当n=0时, 为空树
非空树的性质:
根root, 用r表示
其余节点可分为m个互不相交的有限集合, 其中每个集合本身又是一棵树, 叫做原来树的子树
子树是不相交的
除了根节点, 每个节点有且仅有一个父节点
一棵树N个节点的树有N-1条边
树是保证节点连通的最小的连接方式
树的基本术语
结点的度: 结点的子树的个数
树的度: 树的所有结点中最大的度数
叶结点: 度为0的结点(没有子树)
父结点: 若A有子树, 则A是子树的根节点B的父结点
子结点: 孩子结点, B就是A的子结点
兄弟结点: A有多个子树, 子树1的根节点B, 子树2的根节点C, 那么B和C就是兄弟结点
路径和路径长度: 结点到结点的路径, 路径所包含的边的个数就是长度
祖先节点: B的父节点A的父节点以及它的父节点, 到根为止都是B的祖先结点
子孙结点
结点的层次: 规定根结点的层次为1层
树的深度: 树的最大层次
1.2 树的表示
首先由于树的结构比较复杂, 有父子关系需要存储, 因此不采用数组的方式存储树
一般的, 采用链表的形式来存储树
这样的结构虽然表明了树, 但是由于每个节点的数据结构不统一, 需要改进, 一般的改进策略是孩子兄弟表示法
孩子兄弟表示法
结构中有两个指针域, 一个指向第一个孩子, 另一个执行相邻的兄弟
对于n个结点, 有2n个指针域, 有n-1条边, 因此空余的指针域为(2n-n+1)=n+1
对于这样的表示方式, 如果顺时针旋转45度, 也是一个树的样子, 这个样子就是二叉树
二叉树是度为2的树
一般地解决二叉树的问题能够解决树的很多问题, 二叉树是树研究的重点
2 二叉树及其存储结构
2.1 二叉树的定义和性质
(1) 二叉树的定义
二叉树:一个有穷的结点集合
这个集合可以为空
若不为空, 则它由根节点和其左子树和右子树两个不相交的二叉树组成
二叉树可以被理解为区分左右顺序的度为2的树
二叉树的五种基本形态
(2) 特殊二叉树
只有左子树或者只有右子树
也就是说, 完全二叉树只要是在编号上都能在完美二叉树上对应, 就是完全二叉树
(3) 二叉树的性质
第i层最大的结点数为2i-1
深度为k的二叉树的最大结点数为2k-1
对于非空二叉树, 叶结点个数 = 度为2的非叶结点个数 + 1
证明方式为: 对于非空二叉树, 存在度为0, 1 ,2的结点, 个数分别记为n0, n1, n2
根据 边=所有点-1=n0 + n1 +n2 -1
同时度为0, 1, 2的结点分别提供了0, 1, 2条边
因此 边 = 0*n0 + 1*n1 + 2*n2
得到 n0 + n1 +n2 -1 = 0*n0 + 1*n1 + 2*n2
(4) 二叉树的抽象数据类型定义
最重要的操作方法是遍历
2.2 二叉树的存储结构
(1) 顺序存储结构
可以用数组存储完全二叉树
完全二叉树: 按从上到下, 从左到右顺序存储n个结点的完全二叉树的结点父子关系
存储为
同时可以通过计算得到一个结点的父亲节点, 左孩子, 右孩子
父亲节点是[i/2]向下取整
左孩子是 2i
右孩子是 2i+1
但是如果一般的二叉树采用这样的方式存储的话, 需要填充一部分不存在的元素, 因此会造成很大程度上的空间浪费
(2) 链表存储
3 二叉树的遍历
二叉树一般还是使用链式存储, 二叉树的遍历是基于链式存储的二叉树来的
3.1 递归方式遍历
(1) 先序遍历
根->左->右
(2) 中序遍历
左->根->右
(3) 后序遍历
左->右->根
先序, 中序和后序遍历过程, 遍历过程中经过结点的路线一样, 只是访问输出各结点的时间不同
每个节点实际上有三次输出的机会, 这就对应了先序, 中序和后
3.2 非递归方式
(1) 中序遍历
实现方法:
遇到一个结点, 就把它压栈, 并遍历它的左子树, (遍历左/右子树的时候从第一步开始执行)
左子树遍历完成, 弹出栈顶元素
再访问刚才弹出元素的右子树
实现代码
(2) 先序遍历
根据结论, 先序遍历是在第一次遇到结点的时候就输出, 中序遍历是在第二次遇见的时候输出, 也就是可以将输出语句放到Push操作时就行了
(3) 层次遍历
层次遍历的问题在于, 需要保存左右儿子的信息或者当前元素的信息
使用队列来实现层次遍历
先将根加入队列
从队列中去除一个元素, 并按照顺序将其左右儿子存入队列
输出该元素, 继续第二步骤
3.3 遍历二叉树的应用
(1) 获取叶子结点
在遍历算法中检查左右子树是否都为空, 为空就输出
(2) 求二叉树的高度
求解思想: 二叉树的高度就是 左子树和右子树两个较大的高度+1
通过递归就可以得到二叉树的高度了
(3) 二元运算表达式树及其遍历
表达式树:
通过遍历表达式树可以得到不同的结果
但是我们会发现, 得到的中缀表达式会受到运算符优先级的影响, 需要在输出结点的时候加上括号
(4) 根据两个遍历序列得到整个二叉树
前提, 必须要有中序, 光是前序和后序是无法得到整个树的
实现的方法是
根据中序序列得到一个根节点, 然后在先序序列中找到该结点, 那么在先序序列中前面部分就是左子树
根据这个左子树的长度, 可以在中序序列中找到中序序列的左子树
根据这两个左子树又可以继续找, 直到确定所有元素的位置
以上是关于Mooc数据结构-03树的主要内容,如果未能解决你的问题,请参考以下文章
MOOC数据结构PTA-04-树6 Complete Binary Search Tree