十一、图论

时间:2020-01-24 15:42:52   收藏:0   阅读:70

11.1 图的基本概念

11.2 图的存储

11.2.1 邻接矩阵

11.2.2 邻接表(边表)

注意:如果要保存的图是无向图,则需要双向加边,例如添加一条边 (from, to, w),则需要调用函数 AddEdge(from, to, w); AddEdge(to, from, w); 否则只需要调用一次。

11.2.3 遍历某个结点的邻接点

? 通常我们需要将与某个结点相邻的所有结点遍历一遍,针对图的不同的存储方式,遍历的方式也不相同。

  1. 邻接矩阵存储的遍历

    // 输出与结点 u 相邻的所有结点,简单明了,不解释
    for (int i = 1; i <= n; ++i) {
        if (g[u][i] != -1) { // 假设我们用 -1 表示 u 与 i 之间没有边
            printf("%d ", i);
        }
    }
  2. 邻接表存储的遍历

    ? 这种存图的方式是我们常用的,所以一定要熟练掌握。根据上面给出的不同的构建方法,给出示例代码来输出 结点 u 的所有邻接点编号。

    • 链表(指针实现):

      // 从表头开始,访问完一个邻接点后,通过 next 调到下一个邻接点
      for (Edge* p = head[u]; p != NULL; p = p->next) {
          printf("%d ", p->to);
      }
    • 前向星(数组实现):

      // 从表头开始,访问完一个邻接点后,通过 next 调到下一个邻接点
      for (int i = head[u]; i != -1; i = e[i].next) {
          printf("%d ", e[i].to);
      }
    • vector 实现:

      // 从表头开始,访问完一个邻接点后,通过 next 调到下一个邻接点
      int gs = e[u].size();
      for (int i = 0; i < gs; ++i) {
          printf("%d ", e[i].to);
      }

11.3 图的遍历

11.3.1 深度优先遍历

11.3.2 广度优先搜索

? 广度优先遍历并不常用,从编程复杂度的角度考虑,通常采用的是深度优先遍历。

? 深度优先遍历可以认为是纵向遍历图,而广度优先遍历(Breadth_First_Search)则是横向进行遍历。还以上图为例,不过为了方便查看,我们把上图调整为如下样式:

技术分享图片

? 我们依然以 A 为起点,把和 A 邻接的 B 和 F 放在第二层,把和 B、F 邻接的 C、I、G、E 放在第三层,剩下的放在第四层。

? 广度优先遍历就是从上到下一层一层进行遍历,这和树的层序遍历很像。我们依然借助一个队列来完成遍历过程,因为和树的层序遍历很像,这里只展示结果,如下所示:

技术分享图片

? 广度优先遍历和广搜 BFS 相似,因此使用广度优先遍历一张图并不需要掌握什么新的知识,在原有的广度优先搜索的基础上,做一点小小的修改,就成了广度优先遍历算法。

void bfs(int s) { //邻接表存储图,访问点 s
    queue<int> que;
    visited[s] = true; // 将起点 s 标记并放到队列
    que.push(s);
    
    while (!que.empty()) { // 
        int now = que.front();
        printf("%d ", now);
        for (Edge* p = head[now]; p != NULL; p = p->next) { // 广度优先遍历邻接点
            if (!visited[p->to]) {
                que.push(p->to); // 找到未被访问过的邻接点加入队列,并标记
                visited[p->to] = true;
            }
        }
    }
}

// 假设全局变量已经定义好了
int main() {
    memset(visited, false, sizeof(visited));
    // 如果是有向图,必须用循环才能保证所有的结点都遍历到
    // 如果是连通的无向图,从任一结点开始即可
    for (int i = 1; i <= n; ++i) {
        if (!visited[i]) {
            bfs(i);
        }
    }
    return 0;
}

11.4 欧拉路

11.4.1 基本概念

11.4.2 Hierholzer 算法

11.5 最短路

11.5.1 迪杰斯特拉(Dijkstra)

11.5.1.1 算法思路
11.5.1.2 堆优化的 Dijkstra

原文:https://www.cnblogs.com/hbhszxyb/p/12232227.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!