最短路径算法的编程与实现 C语言

article/2025/8/25 5:46:49

一 、目的:

1.掌握最短路径算法的基本原理及编程实现;

二 、环境:

operating system version:Win11
CPU instruction set:  x64
Integrated Development Environment:Viusal Studio 2022

三 、内容:

1)建立一张图,选择一种存储结构(邻接矩阵或邻接表)初始化该图;
2)用Dijkstra算法实现点与点之间的最短路径。

四 、要求:

1) 实现图的两种表示方法;
2) 实现Dijkstra算法;

五 、步骤:

1. 程序:
 

#include<iostream>  
#define MVNum 100  
#define MaxInt 32767 //极大值,即∞  
using namespace std;  
typedef int ArcType;  
typedef char VerTextType[20];  
int* D = new int[MVNum];  
bool* S = new bool[MVNum];   
int* Path = new int[MVNum];   
typedef struct ArcNode //边结点  
{  int adjver; //该边所指向的顶点位置  struct ArcNode* nextarc; //指向下一条边的指针  ArcType   weight;  
} ArcNode;  typedef struct VNode //顶点信息  
{  VerTextType data;  ArcNode* firstarc;  
} VNode, AdjList[MVNum];  typedef struct node  
{  AdjList vertices;  int     vexnum; //图的当前顶点数  int     arcnum; //图的当前边数  
} ALGraph;  //临接表存储方式最短路径(dijkstra),复杂度O(n^2)  
void ShortestPath_DIJ2(ALGraph G, int v0, ArcType D[], int Path[])  
{  int ok[MVNum], i, j; // ok数组标记是否确定最短路径  for (i = 0; i < G.vexnum; i++) {  ok[i] = 0;  Path[i] = -1;  D[i] = MaxInt;  }  D[v0] = 0;  for (i = 0; i < G.vexnum; i++) {  int min_node = -1;  for (j = 0; j < G.vexnum; j++) {  if (ok[j] == 0 && (min_node == -1 || D[j] < D[min_node])) {  min_node = j;  }  }  if (min_node == -1) break;  ok[min_node] = 1;  ArcNode* cur = G.vertices[min_node].firstarc;  while (cur != NULL) {  if (ok[cur->adjver] == 0 && D[cur->adjver] > D[min_node] + cur->weight) {  D[cur->adjver] = D[min_node] + cur->weight;  Path[cur->adjver] = min_node;  }  cur = cur->nextarc;  }  }  }  //图的邻接矩阵  
typedef struct  
{  char vexs[MVNum];                        //顶点表   int arcs[MVNum][MVNum];                 //邻接矩阵  
}Graph;  void InitGraph(Graph& G, int vex)  
{  cout << "输入点的名称,如a" << endl;  for (int i = 0; i < vex; ++i) {  cout << "请输入第" << (i + 1) << "个点的名称:";  cin >> G.vexs[i];                                       }  cout << endl;  for (int i = 0; i < vex; ++i)  //初始化邻接矩阵,边的权值均置为极大值MaxInt   for (int j = 0; j < vex; ++j)  {  if (j != i)  G.arcs[i][j] = MaxInt;  else  G.arcs[i][j] = 0;  }  
}  //确定点v在G中的位置  
int LocateVex(Graph G, char v, int vex) {  for (int i = 0; i < vex; ++i)  if (G.vexs[i] == v)  return i;  return -1;  
}  //创建无向网G  
void CreateUDN(Graph& G, int vex, int arc)  
{  int i, j, k;  cout << "输入边依附的顶点(node1 node2 weight)" << endl;  for (k = 0; k < arc; ++k) {  //构造邻接矩阵   char v1, v2;  int o;  cout << "请输入第" << (k + 1) << "条边依附的顶点和对应的权值:";  cin >> v1 >> v2 >> o;                                       i = LocateVex(G, v1, vex);  j = LocateVex(G, v2, vex);            G.arcs[j][i] = G.arcs[i][j] = o;                          }  
}  void DisplayGraph(Graph G, int vex)  
{  int i, j;  for (i = 0; i < vex; ++i) {  for (j = 0; j < vex; ++j) {  if (G.arcs[i][j] != MaxInt)  cout << G.arcs[i][j] << "\t";  else  cout << "∞" << "\t";  }  cout << endl;  }  
}  //用Dijkstra算法求无向网G的v0顶点到其余顶点的最短路径   
void ShortestPath_DIJ(Graph G, int v0, int vex) {  int v, i, w, min;  int n = vex;   for (v = 0; v < n; ++v) {                                  S[v] = false;                                         D[v] = G.arcs[v0][v];                                 if (D[v] < MaxInt)  Path[v] = v0;                      else Path[v] = -1;                                    }  S[v0] = true;   D[v0] = 0;  for (i = 1; i < n; ++i) {                                      min = MaxInt;  for (w = 0; w < n; ++w)  if (!S[w] && D[w] < min) {                         v = w;  min = D[w];  }//if             S[v] = true;                                      for (w = 0; w < n; ++w)                              //更新从v0出发到集合V?S上所有顶点的最短路径长度   if (!S[w] && (D[v] + G.arcs[v][w] < D[w])) {  D[w] = D[v] + G.arcs[v][w];                 //更新D[w]   Path[w] = v;                                //更改w的前驱  }  }  for (int i = 0; i < vex; i++) {  if (D[i] != 0)  if (D[i] != MaxInt)  cout << "到" << G.vexs[i] << "最短路径长度:" << D[i] << endl;  else  {  cout << "到" << G.vexs[i] << "最短路径长度:" << "无法到达" << endl;  }  }  
}  int main()  
{  Graph G;  int vexnum, arcnum;   cout << "请分别输入总顶点数和总边数:";  cin >> vexnum >> arcnum;  cout << endl;  InitGraph(G, vexnum);  int v = 0;  CreateUDN(G, vexnum, arcnum);  cout << endl;  cout << "已创建无向图G" << endl << endl;  DisplayGraph(G, vexnum);  int v0 = LocateVex(G, '0', vexnum);  ShortestPath_DIJ(G, v0, vexnum);  
}

2.程序结果:

1)程序运行,我使用的测试数据如下所示:

2)我采用邻接矩阵的方式实现最短路径的存储。创建的无向图G如下:

3)最终通过Dijkstra算法输出源点0到其余节点的最短路径如下:

六 、小结:

       此次是关于Dijkstra最短路径算法的编程与实现。我先分别尝试了采用邻接矩阵以及邻接表的存储结构,比较了他们的优缺点:其中图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息。从这个矩阵中,可以较容易知道图中的信息。1)可以判断任意两顶点是否有边无边;2)可以知道某个顶点的度,其实就是这个顶点vi在邻接矩阵中第i行或(第i列)的元素之和;3)求顶点vi的所有邻接点就是将矩阵中第i行元素扫描一遍,arc[i][j]为1就是邻接点;而邻接表则是将图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储。图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用单链表存储,无向图称为顶点vi的边表,有向图则称为顶点vi作为弧尾的出边表。

        最终我在构建图的时候选择了邻接矩阵的方式实现。通过邻接矩阵的Dijkstra时间复杂度是O(N2)。其中每次找到离1号顶点最近的顶点的时间复杂度是 O(N)。整个程序的基本思想是:设置两个顶点集S和T,集合S中存放已经找到最短路径的顶点,集合T中存放着当前还未找到最短路径的顶点;初始状态下,集合S中只包含源点V1,T中为除了源点以外的其他顶点,此时源点到各顶点的最短路径为两个顶点所连的边上的权值,若是源点V1到该顶点没有边,则最小路径为无穷大;从集合T中选取到源点V1的路径长度最短的顶点Vi加入到集合S中;修改源点V1到集合T中剩余顶点Vj的最短路径长度。新的最短路径长度值为Vj原来的最短路径长度值与顶点Vi的最短路径长度加上Vi到Vj的路径长度值中的较小者;不断重复步骤三、4,直至集合T的顶点所有加入到集合S中。


http://chatgpt.dhexx.cn/article/KaM7hKLh.shtml

相关文章

图的四种最短路径算法

本文总结了图的几种最短路径算法的实现&#xff1a;深度或广度优先搜索算法&#xff0c;弗洛伊德算法&#xff0c;迪杰斯特拉算法&#xff0c;Bellman-Ford算法 1&#xff09;&#xff0c;深度或广度优先搜索算法&#xff08;解决单源最短路径&#xff09; 从起始结点开始访问所…

算法之几个常见的经典最短路径算法

目录 1. Dijkstra算法2. Floyd算法3. Bellman-Ford 算法 1. Dijkstra算法 是解单源最短路径问题的贪心算法。 有一向带权图 G (V, E)&#xff0c;包含右n个顶点&#xff0c;其中每条边的权是非负实数&#xff0c;定义数组 dist 为原点到G中各个顶点的距离&#xff0c;初始化为…

最短路径的四种算法

最短路径四种算法 1234FloydDijkstraBellman-Ford队列优化的Bellman-Ford 一&#xff0c;只有四行的算法——Floyd-Warshall 假设求顶点 V i Vi Vi到 V j Vj Vj的最短路径。弗洛伊德算法依次找从 V i Vi Vi到 V j Vj Vj&#xff0c;中间经过结点序号不大于 0 0 0的最短路径&…

最短路径算法

1.最短路径算法分为单源最短路径算法和多源最短路径算法 &#xff08;a&#xff09;单源最短路径算法&#xff0c;可以计算出从起点到任意一个起点的最短路径。 例如&#xff1a;Dijkstra算法 &#xff0c;SPFA算法 &#xff08;b&#xff09;多源最短路径算法&#xff0c;可…

哈夫曼树及其应用

1、哈夫曼树的基本概念 ---- 哈夫曼&#xff08;Huffman&#xff09;树又称作最优二叉树&#xff0c;它是n个带权叶子结点构成的所有二叉树中&#xff0c;带权路径长度最小的二叉树。 ---- “路径”就是从树中的一个结点到另一个结点之间的分支构成的部分&#xff0c;而分支…

哈夫曼树的C语言实现

什么是哈夫曼树 当用 n 个结点&#xff08;都做叶子结点且都有各自的权值&#xff09;试图构建一棵树时&#xff0c;如果构建的这棵树的带权路径长度最小&#xff0c;称这棵树为“最优二叉树”&#xff0c;有时也叫“赫夫曼树”或者“哈夫曼树”。 在构建哈弗曼树时&#xff0…

哈夫曼树的构建及编码

哈夫曼树的构建及编码 文章目录 哈夫曼树的构建及编码一、什么是哈夫曼树二、什么是哈夫曼编码三、怎么建哈夫曼树、求哈夫曼编码四、为什么哈夫曼编码能实现压缩 声明&#xff1a;关于文件压缩&#xff0c;不是本文的重点&#xff0c;本文只说明并讨论哈夫曼树的构建和编码&am…

如何构建一棵哈夫曼树

给一个数列{10,7,8,3,26,5,1},要求转成为一棵哈夫曼树。 分析思路以及图解&#xff1a; 第一步&#xff1a;将数列进行排序&#xff0c;按从小到大的顺序。最终结果为{1,3,5,7,8,10,26}&#xff0c;根据每个数值创建结点&#xff0c;组成结点数组 第二步&#xff1a;取出权值最…

哈夫曼树 (100分)哈夫曼树

4-1 哈夫曼树 (100分)哈夫曼树 第一行输入一个数n&#xff0c;表示叶结点的个数。 需要用这些叶结点生成哈夫曼树&#xff0c;根据哈夫曼树的概念&#xff0c;这些结点有权值&#xff0c;即weight&#xff0c;题目需要输出哈夫曼树的带权路径长度&#xff08;WPL&#xff09;。…

哈夫曼树的编码和解码

哈夫曼树的作用&#xff1a;在数据通信中&#xff0c;需要将传送的文字转换成二进制的字符串&#xff0c;用0&#xff0c;1码的不同排列来表示字符。例如&#xff0c;需传送的报文为“AFTER DATA EAR ARE ART AREA”&#xff0c;这里用到的字符集为“A&#xff0c;E&#xff0c…

哈夫曼树与哈夫曼编码

哈夫曼树 给定n个权值作为n个叶子结点&#xff0c;构造一棵二叉树&#xff0c;若带权路径长度达到最小&#xff0c;称这样的二叉树为最优二叉树&#xff0c;也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树&#xff0c;权值较大的结点离根较近。 树节点间的边…

【例题】哈夫曼树

【例1】由五个分别带权值为9&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;14的叶子结点构成的一棵哈夫曼树&#xff0c;该树的带权路径长度为_______________。 A、60 B、66 C、67 D、50 答案&#xff1a;C 解析&#xff1a; 关键点在于要学会如何构造哈夫曼树 已知有5…

哈夫曼树以及哈夫曼算法

目录 一、哈夫曼树的定义 二、哈夫曼树的特点 三、哈夫曼算法(构造哈夫曼树的方法) 四、哈夫曼树的构造过程 五、哈夫曼树构造算法的实现 一、哈夫曼树的定义 1、哈夫曼树:最优树即带权路径长度(WPL)最短的树 “带权路径长度最短”是在"度相同”的树中比较而得的结果…

哈夫曼树的绘制

数据结构之哈夫曼树绘制 本人还是一个年轻的程序猿(还是个学生)&#xff0c;请大家多多指教&#xff01; 哈夫曼树 已知权重绘制哈夫曼树 开始我的表演 Step 1. 已知权重&#xff1a;2&#xff0c;3&#xff0c;3&#xff0c;4&#xff0c;7&#xff0c;6 Step 2. 选取其中…

哈夫曼树 哈夫曼编码

哈夫曼树 哈夫曼树的定义&#xff1a;设二叉树具有 n 个带权值的叶节点&#xff0c;那么从根节点到各个叶节点的路径长度与相应叶节点权值的乘积的和&#xff0c;叫作二叉树的带权路径长度 WPL (Weighted Path Length)。具有最小带权路径长度的二叉树称为哈夫曼树 (Huffman Tr…

哈夫曼树(Huffman Tree)

定义 哈夫曼树又称最优二叉树&#xff0c;是一种带权路径长度最短的二叉树。所谓树的带权路径长度&#xff0c;就是树中所有的叶结点的权值乘上其到根结点的路径长度&#xff08;若根结点为0层&#xff0c;叶结点到根结点的路径长度为叶结点的层数&#xff09;。树的路径长度是…

哈夫曼树详解

一、哈夫曼树的介绍 Huffman Tree&#xff0c;中文名是哈夫曼树或霍夫曼树&#xff0c;它是最优二叉树。 定义&#xff1a;给定n个权值作为n个叶子结点&#xff0c;构造一棵二叉树&#xff0c;若树的带权路径长度达到最小&#xff0c;则这棵树被称为哈夫曼树。 这个定义里面涉…

哈夫曼树(Huffmantree)

1.基本概念 哈夫曼树又称为最优树&#xff0c;是一类带权路径长度最短的树。 一些概念的定义&#xff1a; &#xff08;1&#xff09;路径&#xff1a;树的两个结点之间的连线称为路径。 &#xff08;2&#xff09;路径长度&#xff1a;路径上的分支数目称作路径长度。若规定…

哈夫曼树详解及其应用(哈夫曼编码)

一&#xff0c;哈夫曼树的基本概念 路径&#xff1a;从树中一个结点到另一个结点之间的分支构成这两个结点间的路径 结点的路径长度&#xff1a;两结点之间路径上的分支数 树的路径长度&#xff1a;从树根到每一个结点的路径长度之和&#xff0e;记作&#xff1a;&#xff3…

哈夫曼树编码的实现+图解(含全部代码)

目录 哈夫曼树的基本概念 ------------哈夫曼树的构造方法 ------------------------哈夫曼编码 ------------------------------------全部代码 哈夫曼树的基本概念 哈夫曼树通常以二叉树的形式出现&#xff0c;所以也称最优二叉树&#xff0c;是一类带权路径长度最短的树…