四、树的应用

树的应用按考纲来看的话:
1.二叉排序树
2.堆结构
3.哈夫曼(Huffman)树和哈夫曼编码
而刚好这节课刚好都讲到了。
首先,先讲
二叉排序树
也叫二叉查找树/二叉搜索树 BST,Binary Search Tree
主要特性是:左<中<右
一些用的到的特殊函数:
①Position Find(Elemtype X,BinTree BST)
//查找值为X的位置,返回地址
这里用尾递归(可用循环实现),其查找效率取决于树的高度,当出现斜二叉树时是效率很差的情况。解决方法:平衡二叉树(后面讲)
②Position FindMin(BinTree BST)
主要实现是不断往左递归(循环也可实现)
③Position FindMax(BinTree BST)
往右不断递归
④BinTree Insert(Elemtype X,BinTree BST)
//插入,注意仍保持二叉排序树的特性:左<中<右
eg 十二个月份按字典序插入
eg BST->Right = Insert(X,BST->Right);
例子中递归返回的树妖赋值给其右子树,即记录下插入位置
⑤BinTree Delete(Elemtype X,BinTree BST)
//删除比较麻烦,先查找后删除,根据结点不同分三种情况
(1)删叶结点
(2)有一个儿子的结点:让父亲->孙子
(3)有左右两个儿子的结点:两种方案实现,一是 右子树找个最小的来代替,并记得再递归删掉那个结点;二是 左子树里找个最大的来代替,并递归删掉那个结点。
因为是最值,一定只有一个儿子,可以转至(2)(1)。
例子中和插入一样,删除的位置要记录,因此
BST->Right = Insert(X,BST->Right);有类似这样的表示

平衡二叉树
AVL树 Balanced Binary Tree
上面说到我么为了提高查找效率,引入平衡二叉树的概念,其根本是为了降低树的高度,最好是降到log2N。
因此我们让左右结点、高度相差尽量低。
引入平衡因子balance fator的概念BF(T)=h左-h右
每个结点,注意是每个BF的绝对值<=1,或本身是个空树即是AVL树。
高度为h的AVL树最少有几个结点呢?列举可以发现一个规律n(h)=n(h-1)+n(h-2)+1,我们想到斐波那契数列,因此算出nh的值,得出其复杂度。
n个结点AVL树的查找效率是log2n。
AVL树的调整
我们要将不平衡->平衡,本质还是个二叉排序树,注意保持左<中<右的特点成立
这里算个难点,分为四种
1.右单旋(RR旋转) 麻烦结点在右子树的右子树的下面(接在左右都可)
2.左单旋(LL旋转)麻烦结点在左子树的左子树的下面
3.LR旋转 麻烦结点在左子树的右子树的下面
4.RL旋转 麻烦结点在右子树的左子树的下面


CPU在处理时,肯定不能按时间顺序处理,而是按优先顺序处理,怎么体现这个优先队列(按优先权大小顺序取出)呢,就是用堆。
存储方式决定了执行效率,假设分别按下面几种存储结构来存储,他们的时间复杂度分别如下所示:
数组:插入O(1)查找O(1)删除O(n)
链表:插入O(1)查找O(n)删除O(1)
有序数组:查找O(n)或O(logn)插入O(n)删除O(1)
有序链表:查找O(n)插入O(1)删除O(n)
树:二叉搜索树,效率很高,但一直删除最值后,导致树倾斜,效率明显下降
我们重点关注删除的复杂度。
最大堆
始终注意两点
1.结构性:数组表示成完全二叉树
2.有序性:任一结点的关键字是其子树的所有结点的最大(小)值
最大堆Maxheap/大顶堆
最小堆Minheap/大顶堆
其结构体如下

 struct HeapStruct{
 Elemtype *Elements;
 int Size;
 int Capacity;
  }

操作上主要有:
建堆
判满
判空
插入
1.若不满,插入到Size+1的位置,先保证其完全二叉树结构
2.保证其有序性,与父结点比较,换位置,即[i/2]与[i]循环比较
删除
1.先用最后元素替补最大值位置,先保证其完全二叉树结构
2.保证其有序性,比较左右儿子,与大的换位置,循环比较
时间复杂度为logn
最大堆的建立
法1.一个个插入 O(logn)
法2.在线性时间复杂度下建①N个形成二叉树②先保证有序性再调整(注意是从下往上调,从后往前调,直至整个最大堆完成)

哈夫曼树
最优二叉树/WPL最小的二叉树
查找效率:出现比例*比较次数
目的:构造效率最好的搜索树
WPL带权路径长度:∑Wk·Lk
其中带权值Wk,根结点到每个叶结点的长度Lk

typedef struct TreeNode *HuffmanTree;
 struct TreeNode {
 int Weight;
 HuffmanTree Left,Right;
  }

构造方法
循环将权值最小的两个形成二叉树
选取两个最小值可使用刚讲过的堆来实现(排序也可实现,但效率低)
复杂度O(nlogn)
哈夫曼树的特点:
①没有n为1的结点
②n个叶结点,共有2n-1个结点
③左右子树交换仍未哈夫曼树
④同一权值可能有不同构的哈夫曼树,但最优化值一样
哈夫曼编码
一段字符串,要使存储空间最少
eg ASCII 588=464位
实际只有8种字符的话 58
3=174位即可
还能更少,让出现频率高的字符占用更少的空间
即不等长编码
关键是避免二义性,让根结点不成为子结点的前缀码
把二叉树用于编码,构造出代价最小的二叉树,即哈夫曼树

集合
主要涉及 交、并、补、差、判定属于
没怎么认真听

思考:

  1. 关于AVL树的调整,感觉自己只是知其然,大概知道怎么调整,不知道考试的深度是怎么样,考的有多细,mark下吧,过下一遍再看下
  2. 老师给的讨论题 AVL树能否用两边的结点树差来定义呢?貌似挺复杂的,大家可以想一想
  3. 树与森林部分是否和集合类似?后续会补充这方面内容。

你可能感兴趣的:(四、树的应用)