From f9b948524581dbbe4a2713c70427e6658730f525 Mon Sep 17 00:00:00 2001 From: Didnelpsun <2675350965@qq.com> Date: Wed, 28 Apr 2021 23:38:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=BE=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Data-Structrue/graph.md | 40 ++++++++ Data-Structrue/tree.md | 210 +++++++++++++++++++++++++++++++++------- 2 files changed, 215 insertions(+), 35 deletions(-) create mode 100644 Data-Structrue/graph.md diff --git a/Data-Structrue/graph.md b/Data-Structrue/graph.md new file mode 100644 index 0000000..47e54ff --- /dev/null +++ b/Data-Structrue/graph.md @@ -0,0 +1,40 @@ +# 图 + +## 基本概念 + +### 图的定义 + +图是顶点集和边集构成的二元组,即图G由顶点集V和边集E组成,记为G=(V,E),其中V(G)表示图G中顶点的有限非空集,E(G)表示图G中顶点之间的关系(边)集合。 + +若V=$\{v_1,v_2\cdots,v_n\}$,则用|V|表示图G中顶点的个数,也称图G的阶,E=$\{(u,v)|u\in V,v\in V\}$,用|E|表示图G中边的条数。 + +图一定是非空的,即V一定是非空集。 + +### 图的类别 + +#### 无向图 + +若E是无向边(简称边)的有限集合时,则图G为无向图。边是顶点的无序对,记为(v, w)或(w,v),因为(v, w)=(w,v),其中v、w是顶点。可以说顶点w和顶点v互为邻接点。边(v, w)依附于顶点w和v,或者说边(v, w)和顶点v、w相关联。 + +#### 有向图 + +若E是有向边(也称弧)的有限集合时,则图G为有向图。弧是顶点的有序对,记为,其中v、w是顶点,v称为弧尾,w称为弧头,称为从顶点v到顶点w的弧,也称v邻接到w,或w邻接自v。≠。 + +#### 简单图 + +不存在重复边,且不存在顶点到自身的边。一般的图默认是简单图。 + +#### 多重图 + +图G中某两个结点之间的边数多于一条,又允许顶点通过同一条边与自己关联。 + +### 顶点的度 + +对于无向图,顶点v的度是指依附于该顶点的边的条数,记为TD(v)。$\sum_{i=1}^nTD(v_i)=2\vert E\vert$。 + +对于有向图,入度是指以顶点v为终点的有向边的条数,记为ID(v);出度指以顶点v为起点的有向边的条数,记为OD(v);顶点v的度就是其入度和出度之和,即TD(v)=ID(v)+OD(v)。$\sum_{i=1}^nID(v_i)=\sum_{i=1}^nOD(v_i)=\vert E\vert$。 + +### 顶点的关系 + ++ 路径:从一个点到另一个点所经过的顶点序列。 ++ 回路(环):第一个顶点与最后一个顶点相同的路径。 \ No newline at end of file diff --git a/Data-Structrue/tree.md b/Data-Structrue/tree.md index 8f0b8c0..f5a4bfe 100644 --- a/Data-Structrue/tree.md +++ b/Data-Structrue/tree.md @@ -207,20 +207,24 @@ ### 调整最小不平衡树 +最重要的是根据二叉排序树的大小关系算出从大到小的序列,然后把最中间的作为新根,向两侧作为左右子树。 + #### 从结点的左孩子的左子树中插入导致不平衡 ```terminal A(2) | - ----------- - | | - B(1) AR(H) + ------------ + | | + B(1) AR(H) | ------------ | | BL(H+1) BR(H) ``` +BL < B < BR < A < AR + 由于在结点A的左孩子B的的左子树BL上插入了新结点,A的平衡因子由1变成了2,导致以A为根的子树失去了平衡,需要进行一次向右的旋转操作。 将A的左孩子B向右上旋转代替A成为根节点,将A结点向右下选择为成B的右子树的根结点,而B的原右子树则作为A结点的左子树。 @@ -228,39 +232,41 @@ BL(H+1) BR(H) ```terminal B(0) | - ----------- - | | -BL(H+1) A(0) - | - ------------ - | | - BR(H) AR(H) + ------------ + | | +BL(H+1) A(0) + | + ------------ + | | + BR(H) AR(H) ``` #### 从结点的右孩子的右子树中插入导致不平衡 ```terminal - A(-2) - | - ----------- - | | -AL(H) B(-1) - | + A(-2) + | + ------------ + | | +AL(H) B(-1) + | ------------ | | BL(H) BR(H+1) ``` +AL < A < BL < B < BR + 由于在结点A的右孩子(R)的右子树(R)上插入了新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要一-次向左的旋转操作。 将A的右孩子B向左上旋转代替A成为根结点,将A结点向左下旋转成为B的左子树的根结点,而B的原左子树则作为A结点的右子树。 ```terminal - B(0) - | - ----------- - | | - A(0) BR(H+1) + B(0) + | + ------------ + | | + A(0) BR(H+1) | ------------ | | @@ -270,31 +276,165 @@ AL(H) BR(H) #### 从结点的左孩子的右子树中插入导致不平衡 ```terminal - A(2) - | - ----------- - | | - B(1) AR(H) + A(2) + | + ------------ + | | + B(-1) AR(H) | ------------ | | -BL(H) BR(H+1) +BL(H) C(-1) + | + ------------ + | | + CL(H-1) CR(H) ``` ```terminal - B(0) - | - ----------- - | | -BL(H+1) A(0) + A(2) | - ------------ - | | - BR(H) AR(H) + ------------ + | | + B(-1) AR(H) + | + ------------ + | | +BL(H) C(-1) + | + ------------ + | | + CL(H) CR(H-1) +``` + +将BR拆分为C和CL、CR,假设插入的是CR部分,插入CL也同理 + +BL < B < CL < C < CR < A < AR + +由于在A的左孩子(L)的右子树(R)上插入新结点,A的平衡因子由1增至2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先左旋转后右旋转先将A结点的左孩子B的右子树的根结点C向左上旋转提升到B结点的位置,然后再把该C结点向右上旋转提升到A结点的位置。 + +```terminal + C(0) + | + -------------------- + | | + B(1) A(0) + | | + ------------ ------------ + | | | | +BL(H) CL(H-1) CR(H) AR(H) +``` + +```terminal + C(0) + | + -------------------- + | | + B(0) A(-1) + | | + ------------ ------------ + | | | | +BL(H) CL(H) CR(H-1) AR(H) ``` #### 从结点的右孩子的左子树中插入导致不平衡 +```terminal + A(-2) + | + ------------ + | | + AL(H) B(1) + | + ------------ + | | + C(1) BR(H) + | + ------------ + | | +CL(H) CR(H-1) +``` + +```terminal + A(-2) + | + ------------ + | | + AL(H) B(1) + | + ------------ + | | + C(1) BR(H) + | + ------------ + | | +CL(H-1) CR(H) +``` + +AL < A < CL < C < CR < B < BR + +由于在A的右孩子(R)的左子树(L). 上插入新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先右旋转后左旋转。先将A结点的右孩子B的左子树的根结点C向右上旋转提升到B结点的位置,然后再把该C结点向左上旋转提升到A结点的位置。 + +```terminal + C(0) + | + -------------------- + | | + A(0) B(-1) + | | + ------------ ------------ + | | | | +AL(H) CL(H) CR(H-1) BR(H) +``` + +```terminal + C(0) + | + -------------------- + | | + A(0) B(-1) + | | + ------------ ------------ + | | | | +AL(H) CL(H-1) CR(H) BR(H) +``` + +### 哈夫曼树 + +#### 哈夫曼树的定义 + ++ 路径和路径长度:从树中的一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目称作路径长度。 ++ 结点的权:有某种现实含义的数值。 ++ 结点的带权路径长度:从根到该结点的路径长度(经过边数)与该结点权的乘积称为结点的带权路径长度。 ++ 树的带权路径长度:树中所有**叶子**的带权路径长度之和称为树的带权路径长度$WPL=\sum_{i=1}^nw_il_i$。 ++ 哈夫曼树(最优二叉树):带权路径长度最短的二叉树。 + +#### 构造哈夫曼树 + +给定n个权值分别为$w_1, w_2\cdots w_n$的结点,构造哈夫曼树的算法描述如下: + +1. 将这n个结点分别作为n棵仅含一个结点的二叉树,构成森林F。 +2. 构造一个新结点,从F中选取两棵根结点权值最小的树作为新结点的左、右子树,并且将新结点的权值置为左、右子树上根结点的权值之和。 +3. 从F中删除刚才选出的两棵树,同时将新得到的树加入F中。 +4. 重复步骤2和3,直至F中只剩下一棵树为止。 + ++ 每个初始结点最终都会变成叶子结点,且权值越小到根结点的路径长度越长。 ++ 哈夫曼树的结点总数为2n-1。 ++ 构建哈夫曼树时,都是两个两个合在一起的,所以没有度为一的结点,即n1=0。 ++ 哈夫曼树不唯一,但是WPL必然最优。 + +哈夫曼树适合采用顺序结构:已知叶子结点数n0,且n1=0,则总结点数为2n2+1(或2n0-1),且哈夫曼树构造过程需要不停地修改指针,用链式存储的话很容易造成指针偏移。 + +#### 哈夫曼编码 + +哈夫曼编码基于哈夫曼树,利用哈夫曼树对01的数据进行编码,来表示不同的数据含义,因为哈夫曼树必然权值最小,所以对于越常使用的编码越短,越少使用的编码越长,所以发送信息的总长度是最小的。 + +将编码使用次数作为权值构建哈夫曼树,然后根据左0右1的原则,按根到叶子结点的路径就变成了哈夫曼编码。 + +哈夫曼编码是可变长度编码,即允许对不同字符用不等长的二进制表示,也是一个前缀编码,没有一个编码是另一个编码的前缀。 + +同样哈夫曼编码也可以用于压缩。 + ## 树与森林 ### 树的存储结构