贪心法则
算法实现
先定义一个dist数组,用来存放原点到各个顶点的最小距离,初始化为无穷大,dist[原点]=0
再定义个visisted[],表示这个点有没有被访问
再定义个prev[i],如果prev[i]=j,表示结点i的前一个结点是j
- n个顶点,每次找最小的,一共找n-1次。
- 从dist中找到未标记的visisted[]=false的dist[i]最小的顶点u,则visisted[u]
- 再遍历u的邻接点j{j=0,1,...n},如果dist[u]+u到该点的距离 小于 dist[该点j],则更新dist[j]=dist[u]+u到该点的距离 ,则prev[j]=u
参考某博主
//
// Created by w on 2024/7/2.
//
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
#define MVNum 100 //最大顶点数
#define MaxInt 10000//最大值
typedef struct {
char vexs[MVNum];//顶点表
int arcs[MVNum][MVNum];//邻接矩阵
int vexnum,arcnum;
}AMGraph;
//确定顶点位置,vexs[i]={A,B,C,D,E},v=B,返回1
int LocateVex(AMGraph* G,char v)
{
int i;
for(i=0;i<G->vexnum;i++)
{
if(G->vexs[i]==v)
return i;
}
return -1;
}
//创建无向表
AMGraph* CreateUDN()
{
int i,j,k,w;
char v1,v2;
AMGraph* G= (AMGraph*)malloc(sizeof (AMGraph));
printf("输入总顶点数,边数:\n");
cin>>G->vexnum>>G->arcnum;
getchar();//吸收换行符
printf("依次输入点的信息:\n");
for(int i=0;i<G->vexnum;i++)
{
cin>>G->vexs[i];
}
getchar();
// 初始化邻接矩阵
for(i=0;i<G->vexnum;i++)
{
for(j=0;j<G->vexnum;j++)
{
G->arcs[i][j]=MaxInt;
if(i==j)
G->arcs[i][j]=0;
}
}
for(k=0;k<G->arcnum;k++)
{
printf("输入一条边依附的顶点及权值:\n");
cin>>v1>>v2;
cin>>w;
getchar();
i= LocateVex(G,v1);
j= LocateVex(G,v2);
G->arcs[i][j]=w;
G->arcs[j][i]=w;//a到b是2,b到2也是2
}
return G;
}
int print(AMGraph* G)
{
printf(" ");
for(int i=0;i<G->vexnum;i++)
{
cout<<G->vexs[i]<<" ";//直观的显示j :ABCDEF
}
printf("\n");
for(int i=0;i<G->vexnum;i++)
{
cout<<G->vexs[i]<<" ";//直观的显示i :ABCDEF
for(int j=0;j<G->vexnum;j++)
{
if(G->arcs[i][j]==MaxInt)
printf("∞ ");
else
cout<<G->arcs[i][j]<<" ";
}
printf("\n");
}
}
int Dijkstra(AMGraph* G,int s)
{
//s是起点
int dist[MVNum];//储存顶点与各个顶点的最短距离
int prev[MVNum];//从源到顶点i的最短路径i的前一个结点
bool visited[MVNum];//判断结点没有被访问,先初始化为没有被访问
int i,j,k,u,min;
// 初始化数组
for(int i=0;i<G->vexnum;i++)
{
dist[i]=MaxInt;
visited[i]=false;
if(dist[i]==MaxInt)
prev[i]=0;
else
prev[i]=s;
}
dist[s]=0;//此时dist[i]=0 maxin....
for(k=1;k<G->vexnum;k++)//索引1 也就是第二个顶点开始询问
{
min=MaxInt;
for(i=0;i<G->vexnum;i++)
{
if(dist[i]<min&&!visited[i])
{
u=i;
min=dist[i];
}//dist[0]<min u=i=0;min=0;
}
visited[u]= true;//0结点已被访问
// 遍历与u相连的结点(即u的邻接点),从原点s到u的距离是dist[u],u到下一个结点j的距离是G.arcs[u][j]
// if (从s到u的距离)+(u到j的距离)小于(dist的初始化最小距离也可以说是原点到j的最小距离)
// 则更新dist[j]
for(j=0;j<G->vexnum;j++)
{
if(!visited[j]&&dist[u]+G->arcs[u][j]<dist[j])
{
dist[j]=dist[u]+G->arcs[u][j];
prev[j]=u;
}
}// 新的dist[i]=0 1 maxint....
}
for(i=0;i<G->vexnum;i++)
{
printf("从起点%c到%c的最短路径长度:%d\n",G->vexs[s],G->vexs[i],dist[i]);
int p=prev[i];
printf("path:%c",G->vexs[i]);
while(p!=0)
{
printf("<-%c",G->vexs[p]);
p=prev[p];
}
printf("<-%c\n",G->vexs[s]);
}
}
int main()
{
AMGraph* G=CreateUDN();
printf("该无向图邻接矩阵为:\n");
print(G);
Dijkstra(G,0);
}
//输入总顶点数,边数:
//6 9
//依次输入点的信息:
//A B C D E F
//输入一条边依附的顶点及权值:
//AB 1
//输入一条边依附的顶点及权值:
//AC 4
//输入一条边依附的顶点及权值:
//BC 2
//输入一条边依附的顶点及权值:
//BD 7
//输入一条边依附的顶点及权值:
//BE 5
//输入一条边依附的顶点及权值:
//CE 1
//输入一条边依附的顶点及权值:
//DE 3
//输入一条边依附的顶点及权值:
//DF 2
//输入一条边依附的顶点及权值:
//EF 6