王道考研数据结构代码总结(第六章)


本文包含王道考研讲课中所涉及的数据结构中的所有代码,当PPT代码和书上代码有所区别时以咸鱼的PPT为主,个人认为PPT上的代码比王道书上的代码要便于理解,此外,本博客也许会补充一些额外的代码进来(不仅受限于王道考研),408中冷门考点频出,应该会囊括所有涉及到的代码,这也是我的DS的第二轮复习,希望与大家共勉之。

DS的后四章只有最后一章(排序)涉及大量的代码,而树,图,查找这三章,对于概念的考察比较深入,故本文对于前三章也会进行概念上的整理,代码的话也同样会全部给出。

(2023/06/27)由于博客体量问题,本博客只会总结第六章【图】的知识点与代码

相关文章:
王道考研数据结构代码总结(前四章)
王道考研数据结构代码总结(第五章)

本文持续更新,7/5前必结束


基本定义

G : G r a p h G:Graph G:Graph(图); V : V e r t e x V:Vertex V:Vertex(顶点); E : E d g e E:Edge E:Edge(边)

G G G由顶点集 V V V和边集 E E E组成,记为 G = ( V , E ) G=(V,E) G=(V,E),其中 V ( G ) V(G) V(G)表示图 G G G中顶点的集合【非空】; E ( G ) E(G) E(G)表示图 G G G中边的集合。用 ∣ V ∣ |V| V 表示图 G G G 中顶点的个数,也称图 G G G,用 ∣ E ∣ |E| E 表示图 G G G 中边的条数。

注:线性表可以是空表,树可以是空树,但图不可以是空,即 V V V 一定是非空集, E E E 则不做要求。

在这里插入图片描述
E E E无向边(简称 )的有限集合时,则图 G G G无向图。边是顶点的无序对,记为 ( v , w ) (v, w) (v,w) ( w , v ) (w, v) (w,v),因为 ( v , w ) = ( w , v ) (v, w)=(w, v) (v,w)=(w,v),其中 v 、 w v、w vw 是顶点。可以说顶点 w w w和顶点 v v v互为邻接点。边 ( v , w ) (v, w) (v,w) 依附于顶点 w w w v v v,或者说边 ( v , w ) (v, w) (v,w) 和顶点 v 、 w v、w vw相关联。
在这里插入图片描述
E E E有向边(也称 )的有限集合时,则图 G G G有向图。弧是顶点的有序对,记为 < v , w > <v, w> <v,w>,其中 v 、 w v、w vw是顶点, v v v称为弧尾, w w w称为弧头, < v , w > <v, w> <v,w>称为从顶点v到顶点w的弧,也称 v v v邻接到 w w w,或 w w w邻接自 v v v < v , w > ≠ < w , v > <v, w>≠<w, v> <v,w>=<w,v>

在这里插入图片描述
简单图:①不存在重复边;②不存在顶点到自身的边
多重图:图 G G G中某两个结点之间的边数多于一条,又允许顶点通过同一条边和自己关联,则 G G G为多重图

考研中只讨论简单图

在这里插入图片描述
无向图顶点v的度:是指依附于顶点v的边的条数,无向图的全部顶点的度的和等于边数的2倍;在具有 n n n 个顶点, e e e 条边的无向图中, ∑ i = 1 n T D ( v i ) = 2 e \sum_{i=1}^nTD(v_i)=2e i=1nTD(vi)=2e

有向图顶点v的度
顶点v的入度:以顶点v为终点的有向边的数目(以顶点v为终点,即该有向边指向顶点v,即"入")记为 I D ( v ) ID(v) ID(v)
顶点v的出度:以顶点v为起点的有向边的数目(以顶点v为起点,即该有向边远离顶点v,即"出")记为 O D ( v ) OD(v) OD(v)
顶点v的等于其入度和出度之和,即 T D ( v ) = I D ( v ) + O D ( v ) TD(v)= ID(v)+OD(v) TD(v)=ID(v)+OD(v);具有 n n n 个顶点, e e e 条边的有向图中 ∑ i = 1 n I D ( v i ) \sum_{i=1}^nID(v_i) i=1nID(vi) = = = ∑ i = 1 n O D ( v i ) \sum_{i=1}^nOD(v_i) i=1nOD(vi) = = = e e e

拓扑排序

逆拓扑排序:

// 逆拓扑排序的实现(DFS算法) 

void DFSTraverse(Graph G){
    
                // 对图G进行深度优先遍历 
    for (v = 0; v < G.vexnum; ++ v)
        visited[v] = false;           // 初始化已访问标记数据 
    for (v = 0; v < G.vexnum; ++ v)   // 本代码中是从v=0开始遍历 
        if (!visted[v])
            DFS(G, v);
/* 
注意这里也是没被访问过直接DFS
这是因为第一个节点的DFS就会输出完一个连通分量
全部打印出去后,剩下的点和边也会是一个或多个连通分量,即会出现出度为0的 "线"
此时再次DFS即可 
*/
}

void DFS(Graph G, int v){
    
    
    visit(v);                 // 从顶点v出发,深度优先遍历图G 
    visited[v] = true;           // 设已访问标记 
/* 
为什么不pop?
逆拓扑排序是先输出出度为0的点
所以只要有能往出走,就继续DFS即   if (!visited[w]) DFS(G, w);
故当不能往出走的时候,那么就是找见了出度为0的点
故我们需要打印输出,然后回溯 
*/
    for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighor(G, v, w))
        if (!visited[w]){
    
            // w为u的尚未访问的邻接顶点 
            DFS(G, w);
        }

    print(v);           // 打印顶点 
/*
DFS实现逆拓扑排序:在顶点推栈前输出
此时的栈顶元素就是出度为0的点,符合我们的逆拓扑排序打印点的条件 
逆拓扑排序打印点的条件:
1.找一个出度为0的点输出
2.删除该顶点和所有以它为终点的有向边
无法继续DFS就是找到了出度为0的点
打印顶点其实就相当于出栈,即删除这个结点和以它为重点的有向边 
*/
}

猜你喜欢

转载自blog.csdn.net/qq_52156445/article/details/131420300
今日推荐