数据结构寻找最短路径BFS(邻接矩阵,邻接表),dijkstra,floyd

3 篇文章 0 订阅
2 篇文章 0 订阅

邻接矩阵

//寻找点到点之间的最短路径  BFS  邻接矩阵
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define MAX 1000
bool visit[MAX];  //第i个点是否已经访问
int path[MAX];  //记录第i个点的前驱路径
int dist[MAX];  //走到第i个点的最短路径
int gragh[MAX][MAX];  //记录两点间的连接状态
vector<int> queue;
void BFS(int x,int n);//x为顶点下标
int main(void)
{
    int n, m; //n个节点,m条边
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int begin, end;//从哪指向哪的路径
        cin >> begin >> end;
        gragh[begin][end] = gragh[end][begin] = 1;//1代表连接,0代表未连接
    }

    //初始化
    for (int i = 1; i <= n; i++)
    {
        visit[i] = false;
        path[i] = 0;
        dist[i] = 0;
    }

    BFS(1,n); //从第1个节点到最后一个节点的最短路径

    cout << dist[n] << endl;
    return 0;
}

void BFS(int x,int n)
{
    queue.push_back(x);
    visit[x] = false;
    path[x] = 0;
    dist[x] = 0;

    while (!queue.empty())
    {
        x = queue[0];  //更新x,x为队列中的第一个元素,也是接下来遍历i的前驱点
        queue.erase(queue.begin());

        for (int i = 1; i <= n; i++)//遍历找到连通的路径
        {
            //找到未访问并且与之有连接的点
            if (visit[i] == false&&gragh[x][i]!=0) //如果未访问过,因为先访问一定比后访问路径更少
            {
                queue.push_back(i);
                visit[i] = true;
                dist[i] = dist[x] + 1;
                path[i] = x;
            }
        }
    }

}

邻接表


//寻找点到点之间的最短路径  BFS  邻接矩阵
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define MAX 10005
bool visited[MAX];  //记录是否访问过
int dist[MAX];   //记录到第i个点的最短路径
int path[MAX];   //记录第i个点的前驱节点

typedef struct node  
{
    int num;   //节点的下标
    struct node* next; //指向下一个节点的指针
}NODE;

NODE* head[MAX]; //储存头节点

NODE* Build(NODE* head, int num);
void BFS(NODE* node);
vector<NODE*> queue;
int main(void)
{
    
    int n, m;
    cin >> n >> m;
    //初始化
    for (int i = 1; i <= n; i++)
    {
        head[i] = new NODE;
        head[i]->num = i;
        head[i]->next = NULL;
        visited[i] = false;
        dist[i] = 0;
        path[i] = 0;
    }

    //建立表
    for (int i = 1; i <= m; i++)
    {
        int begin, end;
        cin >> begin >> end;
        head[begin]=Build(head[begin], end);
    }

    //bfs,寻找最短路径
    BFS(head[1]);

    cout << dist[n];
    return 0;
}

NODE* Build(NODE* head, int num)
{
    //新建节点并初始化
    NODE* node = new NODE;
    node->num = num;
    node->next = NULL;

    //找到可以插入的地方
    if (head->next == NULL)
        head->next = node;
    else
    {
        NODE* p = head->next;
        while (p->next != NULL)
            p = p->next;
        p->next = node;
    }
    return head;
}

void BFS(NODE* node)
{
    queue.push_back(node);
    visited[node->num] = true;

    while (!queue.empty())
    {
        NODE* p = queue.front();//用于遍历
        while (p->next != NULL)
        {
            p = p->next;
            queue.push_back(head[p->num]);//把下一个节点的头入队列,注意!!!:这里用的是head[p->num]而不是p
                                          //因为p是单一的节点只是下标和节点head相同,而next不同,真正的节点是head
            
            //未被访问过,进行操作
            if (visited[p->num] == false)
            {
                
                visited[p->num] = true;
                dist[p->num] = dist[queue.front()->num] + 1;
                path[p->num] = queue.front()->num;
            }
        }
        queue.erase(queue.begin());
    }
}

dijkstra

#define _CRT_SECURE_NO_WARNINGS 1
//最短路径 dijkstra算法
//算法介绍: 邻接矩阵储存图,每次选择离出发点最近的一个点,
//        将与这个点相邻的点的路径进行更新,这个点剔除,直到每个点都剔除
//语言:C++
//编译器:visual studio community 2022
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 10005
bool visit[MAX]; //记录这个点是否剔除
int dist[MAX];//起点到此节点的最短路径
int gragh[MAX][MAX]; //图,邻接矩阵
void dijkstra(int x,int n);  //目的是更新dist的值,寻找最短路径
int main(void)
{
    int n, m; //n个节点,m条边
    cin >> n >> m;

    //初始化
    memset(visit, false, sizeof(visit));
    memset(dist, 0x3f, sizeof(dist));
    dist[1] = 0;

    //输入每条边的权值
    for (int i = 1; i <= m; i++)
    {
        int begin, end, data; //从begin指向end,权值为data
        cin >> begin >> end >> data;
        gragh[begin][end] = gragh[end][begin] = data;
    }

    dijkstra(1, n);//起点,节点个数

    cout << dist[n];
    return 0;
}

void dijkstra(int x, int n)
{
    int t = n;
    while (t--)//循环n次,即剔除n个点(即visit=true,n次)
    {

        //寻找离起点最近并且未被访问的点
        int head=0;//=0同时也规避了数组越界问题
        for (int i = 1; i <= n; i++) 
        {
            //意思是want还没有赋过值,或者赋过值就寻找更近的点
            if (visit[i] == false && (head==0||dist[i]<dist[head]))
                head = i;
        }
        visit[head] = true;//这个点标记剔除,因为自己到自己肯定为0


        //找到want之后,遍历与want有连接并且未被访问的节点,更新最小值
        for (int i = 1; i <= n; i++)
        {
            if (visit[i] == false && gragh[head][i] != 0)    
            {
                dist[i] = min(dist[i], dist[head] + gragh[head][i]);
            }
        }

    }
}

输入:6 8
1 3 10
1 5 30
1 6 100
2 3 5
3 4 50
4 6 10
4 5 20
5 6 60
输出:60

floyd

#define _CRT_SECURE_NO_WARNINGS 1
/*floyd算法介绍:动态规划思想,需要求的是起点到终点的距离,但最近距离不一定是直达距离,
所以利用一个中间节点,begin->end变成,min(begin->end,begin->node->end),
假如最短路径是1-3-4,我们从前往后更新,1-3最短路径在过程中也更新了,把路程中的每一段都变成
最小值,最终是最小值。
*/
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 6005
int gragh[MAX][MAX];  //gragh[i][j]是从i到j的最短路径
void floyd(int n);
int main(void)
{
    int n, m;
    cin >> n >> m;

    //初始化
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (i == j) gragh[i][j] = 0;
            else gragh[i][j] = MAX;

    //建立邻接矩阵
    for (int i = 1; i <= m; i++)
    {
        int begin, end, data;
        cin >> begin >> end >> data;
        gragh[begin][end] = gragh[end][begin] = data;
    }

    //弗洛伊德
    floyd(n);

    //输出
    cout << gragh[1][n];  //结果,从起点到终点

    return 0;
}

void floyd(int n)
{
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (gragh[j][i] == MAX) continue;//代表二者间没有连接
            for (int k = 1; k <= n; k++)
            {
                if (j == k) continue; //头尾相等去掉
                gragh[j][k] = min(gragh[j][k], gragh[j][i] + gragh[i][k]);
            }
        }
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值