数据结构笔记[3] Dijkstra算法

Dijkstra算法

Dijkstra算法用于求解连通图中的最短距离问题,对于指定一点,该算法可求解其到其余各点的最短距离。
该算法需要两个辅助数组distance[MAXVEX], last_vertex[MAXVEX],前者用于存储各点到所求点的最短路程,后者用于存储其他的点到所求点路径的上一点。
基本步骤可以概括为:

  1. 初始化,distance[ ]数组为v[i]到v0的距离, last_vertex[]数组为v0(起始点)
  2. 查找距v0最近的点k,将其标记为已找到最短路径
  3. 计算未被标记的点经由k点到v0的路径是否比之前短,若是则将其distance[i]记为该距离,last_vertex[i]记为k
  4. 重复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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值