实验五 图的操作

实验性质:综合性实验

要求:

(1)采用邻接矩阵/邻接表建立图;
(2)采用深度优先/广度优先搜索方式遍历图;
(3)编程实现Dijkstra最短路径算法。

目的:

(1)掌握图的邻接矩阵和邻接表存储方式;
(2)掌握图的遍历算法;
(3)掌握图的实际应用——最短路径算法。

代码

#include <iostream>
using namespace std;

//***邻接矩阵***//
#define MaxInt 32767                 //表示极大值,即∞
#define MVNum 100                   //最大顶点数
bool visited[MVNum],visited2[MVNum];    //初始化标志数组,值为false
typedef int VertexType;         //假设顶点的数据类型为字符型
typedef int ArcType;                  //假设边的权值类型为整型
typedef struct{
    
    
  VertexType vexs[MVNum];               //顶点表
  ArcType arcs[MVNum][MVNum];       //邻接矩阵
  int vexnum,arcnum; //图的顶点数和边数
}AMGraph;

//***邻接表***//
typedef struct ArcNode  //边结点
{
    
    
    int adjvex; //该边所指向的顶点的位置
    struct ArcNode * nextarc;   //指向下一条边的指针
    int info; //和边相关的信息
}ArcNode;
typedef struct VNode    //顶点信息
{
    
    
    int data;
    ArcNode * firstarc; //指向第一条依附该顶点的边的指针
}VNode,AdjList [MVNum]; //AdjList表示邻接表类型
typedef struct
{
    
    
    AdjList vertices;
    int vexnum,arcnum; //图的当前顶点数和边数

}ALGraph;
int LocateVex(ALGraph G,int u); //返回顶点u在图G中的位置
void CreateUDG(ALGraph &G);//邻接表建立无向图
void DFS_AL(ALGraph &G,int v);//邻接表表示图的深度优先搜索遍历
void CreateUDN(AMGraph &G2);  //邻接矩阵法建立有向图
void DFS_AM(AMGraph &G2,int v); //邻接矩阵深度优先搜索遍历
void ShortestPath_DIJ(AMGraph G, int v0);   //Dijkstra算法
void Menu();  //文字菜单提示信息

int main()
{
    
    
    ALGraph G;
    AMGraph G2;
    Menu();
    int v=0,v0=0;
    int i;  //输入的数字
    cout<<"请输入操作代码:";
    cin>>i;
    while(true)
    {
    
    
        switch(i)
        {
    
    
            case 1:
                CreateUDG(G);
                break;
            case 2:
                DFS_AL(G,v);
                cout<<endl;
                break;
            case 3:
                CreateUDN(G2);
                break;
            case 4:
                DFS_AM(G2,v);
                cout<<endl;
                break;
            case 5:
                ShortestPath_DIJ(G2,v0);
                break;
            default:
                if(i<0)
                    return 0;
                else
                {
    
    
                    cout<<"输入的位置非法,请重新输入";
                    break;
                }
        }
        cout<<"请输入操作代码:";
        cin>>i;
    }
    return 0;
}
int LocateVex(ALGraph G,int u) //返回顶点u在图G中的位置
{
    
    
    int i;
    for (i = 0; i < G.vexnum; i++)
    {
    
    
        if (u == G.vertices[i].data)
        return i;
    }
    return 0;
}
int LocateVex(AMGraph G2,int u) //返回顶点u在图G中的位置
{
    
    
    for(int i=0; i<G2.vexnum; i++)
        if(u==G2.vexs[i])
            return i;
    return 0;
}
void CreateUDG(ALGraph &G)  //邻接表法
{
    
    
    cout<<"输入总顶点数,总边数:";
    cin>>G.vexnum>>G.arcnum;    //总顶点数,总边数
    cout<<"输入顶点值:";
    for(int i=0;i<G.vexnum;i++) //输入各点,构造表头结点表
    {
    
    
        cin>>G.vertices[i].data;    //输入顶点值
        G.vertices[i].firstarc=NULL;    //初始化表头结点的指针域为NULL
    }
    cout<<"输入每条边依附的两个顶点:"<<endl;
    for(int k=0;k<G.arcnum;++k) //输入各边,构造邻接表
    {
    
    
        int v1,v2;
        cin>>v1>>v2;    //输入一条边依附的两个顶点
        int i=LocateVex(G,v1); int j=LocateVex(G,v2);
        //确定v1和v2在G中位置,即顶点在G.vertices中的序号
        ArcNode *p1=new ArcNode; //生成一个新的边结点
        p1->adjvex=j;   //邻接点序号为j
        p1->nextarc=G.vertices[i].firstarc; G.vertices[i].firstarc=p1;
        //将新节点*p1插入v1的边表头部
        ArcNode *p2=new ArcNode; //生成另一个对称的新节点*p2
        p2->adjvex=i;   //邻接点序号为i
        p2->nextarc=G.vertices[j].firstarc; G.vertices[j].firstarc=p2;
        //将新节点p2插入顶点v1的边表头部
    }
    cout<<"创建成功"<<endl;
}
void DFS_AL(ALGraph &G,int v)
{
    
    //图G为邻接表类型,从第v个顶点出发深度优先搜索遍历图G
    cout<<v;visited[v]=true; //访问第v个顶点,并置访问标志数组相应分量值为true
    ArcNode *p=G.vertices[v].firstarc;   //p指向v的第一个边结点
    while(p!=NULL)  //边结点非空
    {
    
    
        int w=p->adjvex;    //表示w是v的邻接点
        if(!visited[w])
            DFS_AL(G,w); //如果w未访问,则递归调用DFS_AL
        p=p->nextarc;   //p指向下一个边结点
    }
}
void CreateUDN(AMGraph &G2)  //邻接矩阵法
{
    
    
    //采用邻接矩阵表示法,创建无向网G
    cout<<"输入总顶点数,总边数:";
    cin>>G2.vexnum>>G2.arcnum;  //输入总顶点数,总边数
    cout<<"输入顶点值:";
    for(int i = 0; i<G2.vexnum; ++i)
       cin>>G2.vexs[i];                         //依次输入顶点的信息
    for(int i = 0; i<G2.vexnum;++i) //初始化邻接矩阵,边的权值均为极大值
        for(int j = 0; j<G2.vexnum;++j)
            G2.arcs[i][j] = MaxInt;
    cout<<"输入每条边依附的顶点及权值:"<<endl;
    for(int k = 0; k<G2.arcnum;++k)
    {
    
     //构造邻接矩阵
      int v1,v2,w;
      cin>>v1>>v2>>w; //输入一条边依附的顶点及权值
      int i = LocateVex(G2, v1);
      int j = LocateVex(G2, v2);  //确定v1和v2在G中的位置
      G2.arcs[i][j] = w;  //边<v1, v2>的权值置为w2
      //取消下面注释即建立无向图
      //G2.arcs[j][i] = G2.arcs[i][j]; //置<v1, v2>的对称边<v2, v1>的权值为w
    }
    cout<<"创建成功"<<endl;
}
void DFS_AM(AMGraph &G2, int v){
    
      //图G2为邻接矩阵类型
  cout<<v;
  visited2[v] = true;   //访问第v个顶点
  for(int w = 0; w< G2.vexnum; w++) //依次检查邻接矩阵v所在的行
        if((G2.arcs[v][w]!=MaxInt) && (!visited2[w]))
            DFS_AM(G2, w);
      //w是v的邻接点,如果w未访问,则递归调用DFS
}
void ShortestPath_DIJ(AMGraph G, int v0)
{
    
    
    bool S[MVNum];int D[MVNum],Path[MVNum];
    //用Dijkstra算法求有向网G的v0顶点到其余顶点的最短路径
    int n=G.vexnum;                         //n为G中顶点的个数
    for(int v = 0; v<n; ++v)
    {
    
                   //n个顶点依次初始化
       S[v] = false;                    //S初始为空集
       D[v] = G.arcs[v0][v];            //将v0到各个终点的最短路径长度初始化
       if(D[v]< MaxInt)  Path [v]=v0; //v0和v之间有弧,将v的前驱置为v0
       else Path [v]=-1;                //如果v0和v之间无弧,则将v的前驱置为-1
    }
    S[v0]=true;                     //将v0加入S
    D[v0]=0;                        //源点到源点的距离为0
    /*―开始主循环,每次求得v0到某个顶点v的最短路径,将v加到S集―*/
    int v=0;
    for(int i=1;i<n; ++i)
    {
    
    //对其余n?1个顶点,依次进行计算
        int min= MaxInt;
        for(int w=0;w<n; ++w)
          if(!S[w]&&D[w]<min)
              {
    
    v=w; min=D[w];} //选择一条当前的最短路径,终点为v
        S[v]=true; //将v加入S
        for(int 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的前驱为v
            }
    }
    cout<<"以v0为起点的图的最短路径为:"<<endl;
    for(int i=0;i<G.vexnum;i++)
    {
    
    
        cout<<"v0->v"<<i<<":";
        if(D[i]!=MaxInt) //可以到达
        {
    
    
            cout<<D[i]<<endl;
        }
        else
        {
    
    
            cout<<"不可达,无最短路径"<<endl;
        }
    }
}
void Menu()
{
    
    
    cout << "---------------------------" << endl;
    cout << "****by 夏日****" << endl;
    cout << "---------------------------" << endl;
    cout << "1-----邻接表建立无向图 "<< endl;
    cout << "2-----邻接表表示图的深度优先搜索遍历" << endl;
    cout << "3-----邻接矩阵建立有向图 "<< endl;
    cout << "4-----邻接矩阵表示图的深度优先搜索遍历" << endl;
    cout << "5-----迪杰斯特拉算法计算最短路径(先用邻接矩阵建立有向图)" << endl;
    cout << "   退出,输入一个负数!" << endl;
}

输出示例

1.邻接表建立无向图
在这里插入图片描述
2.邻接表表示图的深度优先搜索遍历
在这里插入图片描述
3.邻接矩阵建立有向图
在这里插入图片描述
4.邻接矩阵的深度优先搜索遍历
在这里插入图片描述
5.迪杰斯特拉算法
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zss192/article/details/106458541