BFS+最短路径+邻接表C++

为了简化实现,我这里的权值默认都是1并且都是有向图,不是1的话,比较费劲,还没想到咋写
因为默认权值都是1,所以BFS出来的第一个要找的末尾节点,的队列中就包含了最短路径,
此时只需要从后往前遍历,找出前驱节点就万事大吉,因为我Node里面vertex1就保存了前驱节点,更具体的代码实现如下

// 链表测试.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<list>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;
struct Node {
public:
    int vertex1;//记录了该节点的前驱节点
    int vertex2;//vertex2是该节点
    Node(int v1, int v2) :vertex1(v1), vertex2(v2) {}
    friend ostream& operator<<(ostream& os, const Node& x) {
        cout << "<" << x.vertex1 << "->" << x.vertex2 << "> ";
        return os;
    }
};
struct Adj {
public:
    int vertex;//该节点
    list<Node> head;//STL的链表
    Adj(int v = 0) :vertex(v), head() {}
    bool operator==(const Adj& a1) {
        return a1.vertex == vertex;
    }
};
queue<Node> q;//BFS用到的队列
vector<Node> AllPath;//存路径的顶点
vector<int> path(1);//没用,忘记删了
vector<Adj> adjacnetList(1);//邻接表
int Start, End;//起始顶点,末尾顶点
void init();//初始化邻接表
void BFSMinDistance();//完成BFS的函数
void printPath();//输出路径
int main()
{
    try
    {
        init();
        BFSMinDistance();
    }
    catch (const std::exception& e)
    {
        cout << e.what();
    }
    
}
//建立邻接表的函数
void init() 
{
    int n, m, a, b;
    cout << "输入顶点数,边数" << endl;
    cin >> n >> m;
    Adj tmp(0);
    list<Node> L;
    cout << "输入顶点和顶点" << endl;
    for (int i = 1; i <= m; ++i) {
        cin >> a >> b;
        auto it = find(adjacnetList.begin(), adjacnetList.end(), Adj(a));//返回指向这个元素的迭代器
        if (it == adjacnetList.end()) {
            adjacnetList.push_back(Adj(a));
            auto iter = find(adjacnetList.begin(), adjacnetList.end(), Adj(a));
            iter->head.push_front(Node(a, b));
        }
        else {
            it->head.push_front(Node(a, b));//添加节点到邻接节点的链表域上
        }
    }
    cout << "输入起始点和终点\n";
    cin >> Start >> End;
}
void BFSMinDistance() {
    try {//Node的第一个参数是前驱,第二个参数是下个顶点
        q.push(Node(0, Start));
        while (!q.empty()) {
            auto iterator = find(adjacnetList.begin(), adjacnetList.end(), Adj(q.front().vertex2));
            if (iterator == adjacnetList.end()) {//没找着
                q.pop();
                continue;
            }
            AllPath.push_back(q.front());
            q.pop();
            //遍历其所有的出边
            for (auto ptrNode = iterator->head.begin(); ptrNode != iterator->head.end(); ++ptrNode) {
            //如果找到就压入路径容器中
                if (ptrNode->vertex2 == End) {
                    AllPath.push_back(*ptrNode);
                    goto End;
                }
                else {//没找着就压入队列
                    q.push(*ptrNode);
                }
            }
        }
        End:
        printPath();
    }
/*
6 8
        
1 3
1 2
2 4
2 6
3 4
3 5
4 5
6 5

1 5
*/
    
    catch (std::exception& e) {
        cout<<e.what();
        cout << "异常!!\n";
    }
}
//从后往前推导出最短路径,由于是从后往前,所以用到了一个栈来倒回去
void printPath()
{
    stack<Node> s;
    s.push(AllPath.back());
    Node x = AllPath.back();
    auto it = AllPath.rbegin();
    ++it;
    while (it != AllPath.rend()) {//如果前面的元素的下一节点是栈顶的元素,则一定是最短路径的元素,压栈
        if (it->vertex2 == s.top().vertex1) {
            s.push(*it);
        }
        ++it;
    }
    s.pop();//把节点的自环去掉,因为最开始的时候为了让队列有元素就自己添加了自环,输出路径的时候要先弹走
    while (!s.empty()) {
        cout << s.top();
        s.pop();
    }
}
/*
6 7

1 2
1 3
2 4
3 4
4 6
4 5
5 6

1 6
*/

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿维的博客日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值