-
广度优先搜索算法
-
Dijkstra 算法(迪杰斯特拉算法)
广度优先搜索算法:
❗算法描述❗:
以 s 为源点,将图划分为不同的层次。s 其本身作为一个层次,表示与 s 间距为 0 的顶点,还有与 s 间距为 1 的顶点、间距为 2 的顶点 …… 按层次检索下来,就得到图的广度优先搜索序列。
从上面的描述就可以看出,广度优先搜索树有这样一个性质:当每条边的长度均为单位长度时,它含有的从 s 出发的所有路径都是最短路径。因此,广度优先搜索树 又被称为 最短路径树。
算法实现✍:
建立一个队列 Q,初始化队列中有一个源点。
进行迭代:将 Q 的顶端元素 取出,以其为源点,检索与源点相邻的点,依次加入队列中。
迭代完成的条件:Q 为空。
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int vexnum, edgenum;
vector<vector<int>> edge;
void BFSTraverse();
int main()
{
cout << "请输入顶点、边的数量:" << endl;
cin >> vexnum >> edgenum;
edge.resize(vexnum, vector<int>(vexnum, 0));
cout << "请输入有向图中的边:" << endl;
for (int i = 0; i < edgenum; ++i)
{
int tmp1, tmp2;
cin >> tmp1 >> tmp2;
edge[tmp1][tmp2] = 1;
}
cout << "广度优先搜索序列为:" << endl;
BFSTraverse();
cout << endl;
return 0;
}
void BFSTraverse()
{
// 访问数组
vector<bool> visited(vexnum, false);
// 存储顶点的队列
queue<int> Q;
Q.push(0);
visited[0] = true;
while (!Q.empty())
{
int s = Q.front();
Q.pop();
//visited[s] = true;
cout << s << ' ';
for (int i = 0; i < vexnum; ++i)
{
// 如果点 i 未被访问 且 s -> i 有路径
if (edge[s][i] == 1 && !visited[i])
{
visited[i] = true;
Q.push(i);
}
}
}
}
Dijkstra算法:
广度优先搜索可以在任何边均为单位长度的图中找到最短路径,对广度优先搜索进行改进,即可得到更有普遍性的迪杰斯特拉算法,它适用于权值为正的图。
❗算法描述❗:
在广度优先搜索的算法基础上进行改进
1)将 访问数组 变为 表示距离的dist数组;
2)改用优先队列实现;
3)添加 辅助数组 prev,prev[u] 存储 从源点 s 到 u 的最短路径上,紧挨 u 并在 u 之前的顶点。这边于输出最短路径。
算法实现✍:
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int vexnum, edgenum;
vector<vector<int>> edge;
vector<int> dist;
void Dijkstra();
// 自定义比较方式为 dist值最小者优先
struct cmp
{
bool operator()(int a, int b)
{
if (dist[a] <= dist[b])
{
return true;
}
else
{
return false;
}
}
};
int main()
{
cout << "请输入顶点、边的数量:" << endl;
cin >> vexnum >> edgenum;
edge.resize(vexnum, vector<int>(vexnum, 0));
cout << "请输入有向图中的边及其权值:" << endl;
for (int i = 0; i < edgenum; ++i)
{
int tmp1, tmp2, temp;
cin >> tmp1 >> tmp2 >> temp;
edge[tmp1][tmp2] = temp;
}
cout << "从源点到其余各点的最小路径长度为:" << endl;
Dijkstra();
for (int i = 1; i < vexnum; ++i)
{
cout << dist[i] << ' ';
}
cout << endl;
return 0;
}
void Dijkstra()
{
// dist数组
dist.resize(vexnum, INT_MAX);
dist[0] = 0;
// 存储顶点的优先队列
priority_queue<int, vector<int>, cmp> Q;
Q.push(0);
while (!Q.empty())
{
// 返回并删除dist值最小的元素
int s = Q.top();
Q.pop();
for (int i = 0; i < vexnum; ++i)
{
// 如果点 i 未被访问 且 s -> i 有路径
if (edge[s][i] != 0 && dist[i] > dist[s] + edge[s][i])
{
dist[i] = dist[s] + edge[s][i];
Q.push(i); //将点 i 加入队列并对队列进行原地构造
}
}
}
}