Dijkstra算法大连理工大学数据结构上机第四章

//Dijkstra算法
#include <iostream>

#include <queue>
using namespace std;

template<class EdgeType>
class Edge
{
public:
    int start,end;//边的起始节点,终止节点
    EdgeType weight;//边的权重(应该可以定义为int)
    Edge()
    {
       start=0;
        end=0;
        weight=0;
    }
    Edge(int st,int en,int w)
    {
        start=st;
        end=en;
        weight=w;
    }
    bool operator > (Edge oneEdge)
    {
        if(weight>oneEdge.weight)
            return true;
        else
            return false;
    }
    bool operator < (Edge oneEdge)
    {
        if(weight<oneEdge.weight)
            return true;
        else
            return false;
    }
};

template<class EdgeType>
class Graph
{
    public:
    int vertexNum; //图中节点个数
    int edgeNum;   //图中边的个数
    int * Mark;    //标记某节点是否被访问
    Graph(int verNum)
    {
        this->vertexNum=verNum;
        edgeNum=0;
        Mark=new int[vertexNum];
        for(int i=0;i<vertexNum;i++)
        {
            Mark[i]=0; //都没有被访问过
        }
    }
    ~Graph()
    {
        delete [] Mark;
    }
    //virtual Edge<EdgeType> FirstEdge(int oneVertex)=0;
    //virtual Edge<EdgeType> NextEdge(Edge<EdgeType> oneEdge)=0;
    int verticesNum()
    {
        return vertexNum;
    }
    int EdgesNum()
    {
        return edgeNum;
    }
    bool isEdge(Edge<EdgeType> oneEdge)
    {
        if(oneEdge.end>=0 && oneEdge.start>=0 && oneEdge.weight>0 && oneEdge.start!=oneEdge.end)//判断条件还不清楚
        {
            return true;
        }
        else
        {
          return false;
        }
    }
    int startOfVertex(Edge<EdgeType> oneEdge)
    {
        return oneEdge.start;
    }
    int endOfVertex(Edge<EdgeType> oneEdge)
    {
        return oneEdge.end;
    }
    EdgeType weight(Edge<EdgeType> oneEdge) //返回oneEdge的权重
    {
        return oneEdge.weight;
    }
    //virtual void setEdge(int start,int end,int weight)=0;
    //virtual void deleteEdge(int start,int end)=0;
};

template<class EdgeType>
class AdjGraph : public Graph<EdgeType >
{
 private:
    int ** matrix;
 public:
    AdjGraph(int verNum):Graph<EdgeType>(verNum)
    {
        matrix =new int * [verNum];
        for(int i=0;i<verNum;i++)
        {
            matrix[i]=new int [verNum];
        }
        for(int i=0;i<verNum;i++)
          for(int j=0;j<verNum;j++)
        {
            matrix[i][j]=999;
        }
    }

    AdjGraph(int verNum,int **  a):Graph<EdgeType>(verNum)
    {
        matrix =new int * [verNum];
        for(int i=0;i<verNum;i++)
        {
            matrix[i]=new int [verNum];
        }
        for(int i=0;i<verNum;i++)
          for(int j=0;j<verNum;j++)
          {

            matrix[i][j]=a[i][j];
          }
    }

    EdgeType getIJ(int i,int j)
    {
        if(i<this->vertexNum && j<this->vertexNum)
        return matrix[i][j];
        else
        {
            cout<<"邻接矩阵越界"<<endl;
            return 0;
        }

    }
    int EdgesNum()
    {
        int edgeNum=0;
        for(int i=0;i<this->vertexNum;i++)
        {
            for(int j=0;j<this->vertexNum;j++)
                if(matrix[i][j]<999)
                    edgeNum++;
        }
        this->edgeNum=edgeNum;
        return edgeNum;
    }
    void disp()
    {
        cout<<endl;
        cout<<"此图的领接矩阵为"<<endl;
        for(int i=0;i<this->vertexNum;i++)
        {
           for(int j=0;j<this->vertexNum;j++)
           {
             cout<<matrix[i][j]<<" ";
           }
            cout<<endl;
         }
    }
    ~AdjGraph()
    {
        for(int i=0;i<this->vertexNum;i++)
        {
            matrix[i]=new int [this->vertexNum];
        }
        delete [] matrix;
    }
    Edge<EdgeType> FirstEdge(int oneVer) //返回顶点的第一条边
    {
        Edge<EdgeType> tem;
        tem.start=oneVer;
        for(int i=0;i<this->vertexNum;i++)
        {
            if(matrix[oneVer][i]<999)
            {
                tem.end=i;
                tem.weight=matrix[oneVer][i];
                return tem;
                //break;
            }
        }
        //cout<<"没有符合条件的边"<<endl;
        //return;
    }
    Edge<EdgeType> NextEdge(Edge<EdgeType> oneEdge)//返回与oneEdg有相同起点的下一条边
    {
        Edge<EdgeType> tem;
        tem.start=oneEdge.start;
        for(int i=oneEdge.end+1;i<this->vertexNum;i++)
        {
              if(matrix[oneEdge.start][i]<999)
              {
                 tem.end=i;
                 tem.weight=matrix[oneEdge.start][i];
                 return tem;
              }
        }
        //cout<<"没有符合条件的边"<<endl;
        //return;
    }
    void visit(int i)
    {
        cout<<i+1<<" ";
    }

    //深度优先搜索
    void DFS(int i)//从i号节点开始深度优先搜索
    {
        this->Mark[i]=1;
        visit(i);
        for(Edge<EdgeType> e=FirstEdge(i);this->isEdge(e);e=NextEdge(e))
        {
             if(this->Mark[e.end]==0)
             {
               DFS(e.end);
             }
        }

    }
    void DFSGraph()//对图进行深度优先搜索
    {
        for(int i=0;i<this->vertexNum;i++)
        this->Mark[i]=0;  //标记都未访问
        for(int i=0;i<this->vertexNum;i++)
        {
            if(this->Mark[i]==0)
            {
                DFS(i);
            }
        }

    }
    //广度优先搜索
    void BFS(int i)//从i号节点开始广度优先搜索
    {
        queue<int> que;
        que.push(i);
        visit(i);
        this->Mark[i]=1;
        int p;
        while(!que.empty())
        {
            p=que.front();
            que.pop();
            this->Mark[p]=1;
            for(Edge<EdgeType> e=FirstEdge(p);this->isEdge(e);e=NextEdge(e))
            {
                if(this->Mark[e.end]==0)
                {//此处要注意,在节点入队时候就要将Mark置为已访问,否则可能会导致同一节点多次入队
                  visit(e.end);
                  this->Mark[e.end]=1;
                  que.push(e.end);
                }
            }
        }
    }

    void BFSGraph()//对图进行广度优先搜索
    {
        for(int i=0;i<this->vertexNum;i++)
        this->Mark[i]=0;  //标记都未访问
        for(int i=0;i<this->vertexNum;i++)
        {
            if(this->Mark[i]==0)
            {
                BFS(i);
            }
        }
       cout<<endl;
    }

};

//Dijkstra算法
template<class EdgeType>
void Dijkstra(AdjGraph<EdgeType>& G,int s,EdgeType D[],int Path[])//从S出发生成最短路径
{
        int n=G.verticesNum();
        for(int i=0;i<n;i++)
        {
            G.Mark[i]=0;
            D[i]=G.getIJ(s,i);
            if(G.getIJ(s,i)<999)
            Path[i]=s;
            else
            Path[i]=-1;
        }
        G.Mark[s]=1;
        D[s]=999;
        Path[s]=s;
        for(int i=0;i<n;i++)
        {
            cout<<"路径数组";
            for(int i=1;i<n;i++)
            {
                cout<<D[i]<<" ";
            }
            cout<<endl;
            EdgeType min=D[0];
            int k=0;
            for(int j=1;j<n;j++)
            {
                //min=D[0];
                if(G.Mark[j]==0 && min>D[j])
                {
                    min=D[j];
                    k=j;
                }
            }
            D[k]=min;
            cout<<"最短的路径为"<<min<<endl;
            G.Mark[k]=1;

            for(Edge<EdgeType> e = G.FirstEdge(k);G.isEdge(e);e=G.NextEdge(e))
            {
                int vertexEnd=e.end;
                if(G.Mark[vertexEnd]==0 && D[vertexEnd]>(D[k]+e.weight))
                {
                    D[vertexEnd]=D[k]+e.weight;
                    Path[vertexEnd]=k;
                    cout<<"更新"<<vertexEnd<<endl;
                }
            }

        }
   D[s]=0;
}


int main()
{
    //课本p170的图
    int tem[6][6]={
        {999, 12, 10,999, 30,100},
        {999,5  ,999,999,999,999},
        {999,999,999,50 ,999,999},
        {999,999,999,999,999, 10},
        {999,999,999, 20,999, 60},
        {999,999,999,999,999,999},
    };
    int n=6;
    int ** a=new int *[n];
    for(int i=0;i<n;i++)
    {
        a[i]=new int [n];
    }
    for(int i=0;i<n;i++)
      for(int j=0;j<n;j++)
    {
        a[i][j]=tem[i][j];
    }

    AdjGraph<int> p(n,a);
    p.disp();
    cout<<"深度优先搜索"<<endl;
    p.DFSGraph();
    cout<<endl;
    cout<<"广度优先搜索"<<endl;
    p.BFSGraph();
    int D[n];
    int path[n];
    Dijkstra(p,0,D,path);
    cout<<"D"<<endl;
    for(int i=0;i<n;i++)
    {
        cout<<D[i]<<" ";
    }
    cout<<endl;
        cout<<"Path"<<endl;
    for(int i=0;i<n;i++)
    {
        cout<<path[i]<<" ";
    }
    cout<<endl;
    return 0;
}

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/L1558198727/article/details/78865209
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞