Dijkstra算法
Dijkstra算法用于求解连通图中的最短距离问题,对于指定一点,该算法可求解其到其余各点的最短距离。
该算法需要两个辅助数组distance[MAXVEX], last_vertex[MAXVEX],前者用于存储各点到所求点的最短路程,后者用于存储其他的点到所求点路径的上一点。
基本步骤可以概括为:
- 初始化,distance[ ]数组为v[i]到v0的距离, last_vertex[]数组为v0(起始点)
- 查找距v0最近的点k,将其标记为已找到最短路径
- 计算未被标记的点经由k点到v0的路径是否比之前短,若是则将其distance[i]记为该距离,last_vertex[i]记为k
- 重复2直到所有点都被标记
算法实现
MGraph.h
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <queue>
#include <assert.h>
using namespace std;
#ifndef _MATRIXGRAPH
#define _MATRIXGRAPH
const int INF { 65535 };
template <class T>
class MGraph
{
private:
vector<T> vexs;
vector<vector<int>> arc;
int m_vexsnum, m_edgenum;
int* k_parent; // use for kruskal
public:
MGraph(bool direction);
MGraph(const char* in_file);
void Print();
bool Save(const char* out_name);
void Dijkstra(int n);
};
#endif
MGraph.cpp
#include "MatrixGraph.h"
using namespace std;
#define _INPUT 0
template <class T>
MGraph<T>::MGraph(bool direction)
{
cout << "Please input the number of vertexs:";
cin >> m_vexsnum;
vexs.resize(m_vexsnum);
arc.resize(m_vexsnum);
for (register int i = 0; i < m_vexsnum; i++) {
arc[i].resize(m_vexsnum);
}
for(register size_t i = 0; i < m_vexsnum; i++)
{
for(register size_t j = 0; j < m_vexsnum; j++)
{
arc[i][j] = (i == j) ? 0 : INF;
}
}
cout << "Please input the number of edges:";
cin >> m_edgenum;
// cout << "Please input vertexs:" << endl;
for(register size_t i = 0; i < m_vexsnum; i++)
{
// cin >> vexs[i];
vexs[i] = i;
}
cout << "Please input [in out weight] of edges:" << endl;
for(register size_t i = 0; i < m_edgenum; i++)
{
int ti{ 0 }, tj{ 0 }, temp{ 0 };
cin >> ti;
cin >> tj;
cin >> temp;
arc[ti][tj] = temp;
if (!direction) { arc[tj][ti] = temp; }
}
visited = nullptr;
}
template<class T>
MGraph<T>::MGraph(const char* in_file)
{
ifstream ifile(in_file, ios::binary);
assert(ifile.is_open());
ifile.read((char*)&m_vexsnum, sizeof(m_vexsnum));
ifile.read((char*)&m_edgenum, sizeof(m_edgenum));
vexs.resize(m_vexsnum);
arc.resize(m_vexsnum);
for (register int i = 0; i < m_vexsnum; i++) {
arc[i].resize(m_vexsnum);
}
for (register int i = 0; i < m_vexsnum; i++) {
ifile.read((char*)&vexs[i], sizeof(T));
}
for (int i = 0; i < m_vexsnum; i++)
{
for (int j = 0; j < m_vexsnum; j++)
{
ifile.read((char*)&arc[i][j], sizeof(int));
}
cout << endl;
}
ifile.close();
visited = nullptr;
}
template<class T>
void MGraph<T>::Print()
{
cout << "Elements:" << endl;
for (register int i = 0; i < m_vexsnum; i++) {
cout << vexs[i] << " ";
}
cout << endl << "Edges:" << endl;
for (register int i = 0; i < m_vexsnum; i++)
{
for (register int j = 0; j < m_vexsnum; j++)
{
cout << setw(7) << arc[i][j] << " ";
}
cout << endl;
}
}
template<class T>
bool MGraph<T>::Save(const char* out_name)
{
ofstream ofile(out_name, ios::binary);
assert(ofile.is_open());
ofile.write((char*)&m_vexsnum, sizeof(m_vexsnum));
ofile.write((char*)&m_edgenum, sizeof(m_edgenum));
for (register int i = 0; i < m_vexsnum; i++) {
ofile.write((char*)&vexs[i], sizeof(T));
}
cout << endl;
for (int i = 0; i < m_vexsnum; i++)
{
for (int j = 0; j < m_vexsnum; j++)
{
cout << setw(3) << arc[i][j] << " ";
ofile.write((char*)&arc[i][j], sizeof(int));
}
cout << endl;
}
ofile.close();
return true;
}
template<class T>
void MGraph<T>::Dijkstra(int n)
{
if (n >= m_vexsnum || n < 0) {
cerr << "Wrong index!" << endl;
return;
}
int* distance = new int[m_vexsnum]; assert(distance);
int* last_vex = new int[m_vexsnum]; assert(last_vex);
bool* is_find = new bool[m_vexsnum]; assert(is_find);
// 初始化,记录所有顶点到所求顶点n直接的距离
for (int i = 0; i < m_vexsnum; i++) {
if (i == n) {
distance[i] = 0;
last_vex[i] = n;
is_find[i] = true;
}
else {
distance[i] = arc[n][i];
last_vex[i] = n;
is_find[i] = false;
}
}
// 循环
for (int i = 1; i < m_vexsnum; i++) {
// 查找未被标记且到n最近的一点
int min{ INF }, k{ n };
for (int j = 0; j < m_vexsnum; j++) {
if (!is_find[j] && distance[j] < min) {
min = distance[j];
k = j;
}
}
// 标记该点
is_find[k] = true;
// 更新其余未标记的点,若经由k点再到n点更近,则更新
for (int j = 0; j < m_vexsnum; j++) {
if (!is_find[j] && (distance[k] + arc[k][j] < distance[j])) {
distance[j] = distance[k] + arc[k][j];
last_vex[j] = k;
}
}
}
cout << "index :";
for (int j = 0; j < m_vexsnum; j++) {
cout << setw(5) << j;
}
cout << "\ndistance:";
for (int j = 0; j < m_vexsnum; j++) {
cout << setw(5) << distance[j];
}
cout << "\nlast_vex:";
for (int j = 0; j < m_vexsnum; j++) {
cout << setw(5) << last_vex[j];
}
cout << endl;
delete[] distance;
delete[] last_vex;
delete[] is_find;
}
int main(void)
{
#if _INPUT
MGraph<int> g(false);
g.Print();
g.Save("Prim_test.dat");
#endif
MGraph<int> g1("Prim_test.dat");
g1.Print();
cout << "\n\nDijkstra:" << endl;
g1.Dijkstra(0);
return 0;
}