数据结构笔记(7)图论算法

(CSDN的markdown是不是有问题啊……代码行总会读取上面的尾巴ε=ε=ε=(#>д<)ノ

关于图的若干定义
(具体参考离散数学......)

G=(V,E)

其中G为图,V为顶点集(vertex),E为边集(edge)
每一条边就是一个点对(v,w),其中v,w∈V
当点对有序时,w和v称为有向的,这样的图称为有向图
当v与w之间存在边时,我们称顶点v与w邻接。
有时边存在着称为权(weight)或值(cost)的属性
邻接表
邻接矩阵(adjacency matrix)
  1. 对于每条边(u,v),我们置A[u][v]=1,否则为0。该方法用于表示稠密(dense)的图,但并不是很有效,空间上的消耗太大了。空间需求为O(|v|^2)
邻接表(adjacency list)
  1. 对每一个顶点,使用一个表存放所有邻接的顶点,此时的空间需求为O(|E|+|V|)
  2. 具体实现:
    • 对每个节点,创建相邻节点的链表
    • 对于有向图,每条边有一个入口
    • 对于正则图,每条边有两个入口【待考】
    • 散列表实现:
      • 每个节点都存储一个名字以及一个内部编号
      • 制定一个编号,f(0)= 1,读入该图
      • 读入每条边,检查是否两个顶点在散列表中,如果在,则使用该内部编号,如果不在,将下一个可用的编号分配给该顶点并将其插入到散列表中。分配好的内部编号就是散列函数最终的结果。
拓扑排序(Topological sort)
  1. 拓扑排序是对有向无圈图的顶点的一种排序,它使得如果存在一条vi到vj的路径,那么在排序中vj在vi的后面。
  2. 拓扑排序不是唯一的。
  3. 算法概述:
    • 找出任意一个入度为0的顶点
    • 输出该顶点
    • 把该顶点与它的边从图中删除
    • 重复以上步骤直至输出完毕
  4. 邻接表实现伪代码描述:

    void Topsort(Graph G)
    {
    int Counter;
    Vertex V,W; 
            for(Counter=0;Counter<numVertex;Counter++)
    {
        V=FindNewVertexOfIndgreeZero();//找到一个入度为0的点,如果这样的点不存在,返回NotAVertex
        if(V==NotAVertex)
        {
            Error("Graph has a cycle");
            break;
        }
        TopNum[V]=Counter;//大概是将V的编号赋为Counter(顺序值)【待考】
        foreach W adjacent to V
            Indegree[W]--;//由于V被删除所以所有前置节点为V的节点,其入度应当减一
    }
    }

  5. 队列实现伪代码描述
    这里写图片描述

最短路径算法
深度优先搜索
  1. 无权最短路径

    • 使用某个顶点s作为输入参数,我们想找到从s到所有其他顶点的最短路径。
    • 选择某点作为s点,并将其标记为0
    • 寻找与s点距离为1的点,将其标记为1
    • 最远的顶点最后被标记
    • 这个方法有点像是对树的层序遍历
  2. 算法概述:我们利用一个存储三种不同信息的表来进行遍历。其中:

    • dv用于存储从s开始到顶点的距离
    • pv用于存储实际的路径(前一节点(的索引))
    • 布尔值Known用于标记节点是否已经处理完成(所找到的路径长为最短)
  3. 伪代码实现:
    这里写图片描述
    该种方法的缺点在于对于最坏情形时执行的很低效。下面给出改进后的伪代码表示:
    这里写图片描述
    队列具有FIFO性,所以入队出队的顺序就是拓扑编号顺序。
Dijkstra算法
  1. 算法概述:在每个阶段,Dijkstra算法选择一个顶点v,它在所有未知定点中具有最小的dv,同时算法声明从s到v的最短路径是已知的,阶段的其他部分由dw值的更新工作完成。

    • dv用于存储使用已知顶点作为中间顶点从s开始到v的最短路径的长。
    • pv用于存储引起dv变化的最后的顶点。
    • 布尔值Known用于标记节点是否已经处理完成(所找到的路径长为最短)
  2. 伪代码实现:
    这里写图片描述
    这里写图片描述

  3. 负边图
  4. 无圈图
最小生成树
  1. 最小生成树:连接图G的所有顶点的边所构成的树,且其总价值最低。
  2. 两种算法的差距:是否需要在执行过程中保持图的连通性。
  3. Prim算法:
    • 每一步都把一个节点当做根并向上加边
    • 在每一阶段都可以通过选择边(u , v),使得(u,v)的值是所有u在树上但v不在树上的边的值中的最小者
  4. Kruskal算法:
    • 连续的按照最小的权选择边,并且当所选的边不产生圈的时候就把它作为选定的边。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值