课程流程:从图的定义到从无向图的一些性质(边数),然后介绍了两种图的表示方法,然后介绍最小生成树,证明了最优子结构和重叠子问题引出动态规划,但是局部最优可以达到全局最优使用贪心算法,然后证明了MST局部最优可以达到全局最优
#something 表示something的数量,如 #E表示边的数量
无向图的性质:
-
无向图:G=(V,E) #E≤V
2
-
#E=O(V
2) 取对数 O(lgV)
连通图(两点有路径可达达):#E>#V-1 取对数 Ω(lgV)【后面算一些下界需要用到】
所以连通图 lg#E=θ(lgV)
图的表示:
一丶邻接矩阵
存储空间:θ(V2) ,浪费
注:从这里我们也可以看出矩阵和图是同一件事物两种不同表示
二丶邻接表
Adj[V]
记录与V相连的点如:Adj[4] ={2,3}
表示4 与2和3连接
#Adj[V] = degree(V)(无向图)=outdegre(V)(有向图)
-
握手定理(无向)
-
度和=2#E
边的存储空间:边最多2E,所以O(E)
总的存储空间:θ(V+E),所以是稀疏表示法
具体
每个顶点建立一个单链表,第 i 个单链表中的结点都依附于顶点vi的边
-
头结点
-
firstarc:指向链表的第一个结点
info:顶点的信息
弧结点
-
adjvex:表示该邻接点在图中的位置
nextarc:指向顶点v i的下一条弧
info:存储弧的信息 如权值
最小生成树
图中找到一个无环的边集连接了所有的节点,且边的权重和最小
分布式系统找到一颗最小生成树,所有节点活跃,海量应用
算法
输入:无向图G=(V,E) ,w(u,v)u到v的权值
输出:一颗生成树
试试可以用动态规划吗?
最优子结构
MST的子树也是对应子图的MST
-
证明T
1 ,T
2同理
-
研究方法:T被分成两个子树T
1,T
2
重叠子问题
有该性质
结论
动态规划可以解决,但隐藏有一个更加强大的属性: 局部最优也是全局最优,使用贪心算法,更牛逼
Prim 算法
-
图解释
-
Prim算法有两个集合,一个就是已经知道了路径的S,还有就是未知的G-S,
图中 绿色点表示现在S可以直连的,也知道这些连接点边的长度
图中 红色点表示现在S不可以直连的,也不知道这些连接点边的长度,必须等其他点加入S后才能获取
图中 黑色点表示根本连接不上的点,不在一个连通分量中
Pseudocode
Prim 算法使用的就是贪心,每次选择连接到的绿色点的边中权重最小,然后把那个点u加入S
然后更新u的不属于S集合的邻居
可以使用贪心证明
也就是证明局部最优达到全局最优证明
不看树的其他部分,我们只看一部分,把这部分连接到外面的部分我们选择最小的最好,这就是贪心,虽然局部最优,但是可以达到全局最优,证明如下
prim(G,W,S)
{
foreach(v∈G.v) d[v] = +∞
d[s]=0
Q=V
while(Q!=null)
{
u=Extract_min(Q) //贪心所在
foreach(v∈Adj[u])
if(v∈S && d[v]>w[u,v])
{
d[v]=w[u,v]
Decrease_key(v)
path.v=u
}
}
这里Q是二叉堆而成的优先队列
运行时间分析:
也就是分析Extract_min和Decrease_key(v)次数
- Extract_min(Q)也就是顶点的个数V
- Decrease_key(v)也就是度的和(握手定理) O(E)