图论算法整理(杂)

    整理一些有关图论算法的东西,整理得比较随意,而且也是先整理一些,之后想到啥就补充一点改一点,所以在标题上写个杂。这篇笔记纯粹是整理着自己玩,所以 C++ 代码写得也很随意。

邻接表、拓扑排序

    先来看一个有向图无环图。
在这里插入图片描述
    该有向图的全体边为:

(A, B), (A, C), (A, F), (B, D), (B, E), (C, E), (D, C), (D, F), (F, E)

    邻接表的结构也一目了然:

在这里插入图片描述
    写点代码,输入边,输出邻接表,写得可以说是很随意了:

#ifndef GRAPH_GRAPH_H
#define GRAPH_GRAPH_H
#include <unordered_map>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
class graph {
public:
    void insert(string, string);//输入
    void print();//输出邻接表
private:
    unordered_map<int,vector<int>> adjacencylist;//邻接表
    vector<int> Indegree;//入度数组
    unordered_map<string,int> node2index;//值到内部编号的哈希表
    unordered_map<int,string> index2node;//内部编号到值的哈希表
    int node_num = 0;//节点数
};
void graph::insert(string s1,string s2){
    if(node2index.find(s1) == node2index.end()){
        node2index[s1] = node_num;
        index2node[node_num] = s1;
        ++ node_num;
        Indegree.push_back(0);
    }
    if(node2index.find(s2) == node2index.end()){
        node2index[s2] = node_num;
        index2node[node_num] = s2;
        ++ node_num;
        Indegree.push_back(0);
    }
    adjacencylist[node2index[s1]].push_back(node2index[s2]);
    ++Indegree[node2index[s2]];
}

void graph::print() {
    for(int i = 0; i < node_num; ++i){
        cout << index2node[i]<<' ';
        for(int j = 0; j < adjacencylist[i].size(); ++j){
            cout<< index2node[adjacencylist[i][j]]<<' ';
        }
        cout<<endl;
    }
}

#endif //GRAPH_GRAPH_H

在这里插入图片描述
    拓扑排序就是把有向无环图的节点排成一个序列,注意这个“有向”,点的顺序不能反了,如果有边(A,B),那么在序列中A一定在B前面。
    贴代码,重复的就不贴了

#ifndef GRAPH_GRAPH_H
#define GRAPH_GRAPH_H
#include <unordered_map>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class graph {
public:
	...//同上
    vector<string> topsort();
private:
	...//同上
    int find_zero_indegree();//找入度为0的点,就是找入口呗
};
	...//同上
int graph::find_zero_indegree() {
    auto iter = find(indegree.begin(), indegree.end(), 0);
    if (iter == indegree.end())
        return -1;
    else {
        return iter - indegree.begin();
    }
}
vector<string> graph::topsort() {
    vector<string> topsort_result;
    for (int i = 0; i < node_num; ++i) {
        int innode = find_zero_indegree();
        if (innode == -1) {
            cout << "有环";//还没输出全部的点就找不到入度为0的点了,说明有环
            break;
        }
        indegree[innode] = -1;//删去这个点,直接入度为-1就行了
        topsort_result.push_back(index2node[innode]);
        for (auto outnode : adjacencylist[innode]) {
            --indegree[outnode];
        }
    }
    return topsort_result;
}
#endif //GRAPH_GRAPH_H

    输入上面的例子看结果:
在这里插入图片描述
    有环的话会怎么样呢?当然是输出有环啦,不信看下面:
在这里插入图片描述
    这样子搜索入度为 0 的点实在太憨了,浪费时间,借助队列可以节省时间。就是先把度为 0 的节点入队,之后队列出队,对出队的节点的后继节点的入度减 1,注意减到 0 就要入队,如此循环。最后队列空了,即没有入度为 0 的点了,循环结束,如果结果中的点没有包含全部节点,说明有环。去掉搜索 0 入度的成员函数,修改拓扑排序的函数如下。

vector<string> Graph::topsort() {
    vector<string> topsort_result;
    queue<int> Q;//辅助队列
    for (int i = 0; i < node_num; ++i) {
        if (indegree[i] == 0) Q.push(i);
    }
    while (!Q.empty()) {
        int cur = Q.front();
        Q.pop();
        topsort_result.push_back(index2node[cur]);
        for (auto index : adjacencylist[cur]) {
            if (--indegree[index] == 0)
                Q.push(index);
        }
    }
    if (topsort_result.size() != node_num) {
        cout << "有环" << endl;
    }
    return topsort_result;
}

最短路径算法

    无人驾驶中有什么路径规划,什么全局路径规划,局部路径规划,计算机网络讲网络层的时候有什么路由选择算法,其实归根结底都可以理解为求最短路径的问题(反正我是这么理解的),当然要达到这个最短可以考虑时间、空间,无人驾驶上还考虑路径的拥堵程度,还有其他各种东西,这里就把这一切东西都算到所谓的“权”上(无权图怎么办?无权图虽然边上没有权,路径长短只和边的数量有关,那就不妨想象全体边的权为1呗)。

Dijkstra算法(还没写全)

    这个算法我每次看懂后过会就忘,没办法,算法这种东西还是得多用才能记住。这里就再总结一下理论,写点代码吧。
    来看一个有向带权图及对应的邻接表:
在这里插入图片描述
在这里插入图片描述
    若要知晓某个点(源节点,这里不妨设为 A),到其他各个节点的最短路径,可以用Dijkstra算法实现。设节点数量为 N,该算法通过 N 次迭代即可得到源节点到全体节点的最短路径及对应的长度(权值和)。在迭代的过程中不断更新源节点到其他每个节点的路径长度d,路径是否已知K,以及每个目标节点的前驱节点p。首先初始化这些信息,这里大家一开始都没有前驱,出来源节点本身外,其他节点对应的路径长度都是无穷大。之后每次迭代都找出路径最短的点,更新其相邻节点的信息。从这里可以用一个表来容纳这些信息,算法的执行过程如下。
在这里插入图片描述
    这里最后一次迭代完成后,源节点到其他每个节点的最短路径长度就都知道了,并且由于每个节点的前驱节点也都记录了,因此源节点到其他每个节点的最短路径也能方便得得到。
    写点C++代码。由于每次迭代都要找路径最短的节点,所以不妨构建一个小顶堆,这样子找最小值方便,不过更新值就麻烦了。对于程序输入,不仅要和之前一样输入边,还要输入权值。另外现在还带有权值了,之前写的沙雕代码又要改改了,哭了。

/*
此处正在维护,请稍等。。。。。
*/

(未完待续哈哈哈!)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值