数据结构课程设计——图的建立和遍历(邻接矩阵+邻接表)和最短路径dijkstra路径记录

数据结构课程设计,根据之前数据结构实践报告图的遍历修改而成,增加了对图使用dijkstra最短路径算法并记录路径,增加了交互界面,功能选择,异常处理等内容。具体使用邻接矩阵实现,邻接表未被调用但保留代码。

原代码请移步:数据结构图的建立

以上链接包括了代码中保留部分,各个模块包括建图(邻接矩阵、邻接表),BFS广搜,DFS模块都有说明。本文仅说明代码增加内容,交互界面异常处理和dijkstra最短路径计算,记录应用。

最短路径代码:

void dijkstra(MGraph G)
{
    string tmp;
    int pre[108];///父亲记录数组,回溯寻找路径
    int dist[MAX_VERTEX_NUM],s;///最短路数组
    bool vis[MAX_VERTEX_NUM];///标记数组
    printf("请输入该图起点:");
    while(cin>>tmp)///最短路源点
    {
        if(tmp=="END")break;
        s=LocateVex(G,tmp);
        if(s==-1)
        {
            printf("输入的起点不存在,请重新输入\n");
            continue;
        }
        for(int i=0; i<G.vexnum; i++)pre[i]=s;///路径父亲初始化
        memset(vis,false,sizeof(vis));
        memset(dist,0x3f,sizeof(dist));
        for(int i=0; i<G.vexnum; i++)///所有点到达起点的距离
            dist[i]=G.arcs[s][i].adj;
        dist[s]=0;///标记起点长度为0
        vis[s]=true;///标记走过
        for(int i=1; i<G.vexnum; i++)///遍历n-1次
        {
            int minn=0x7fffffff,mini;
            for(int j=0; j<G.vexnum; j++)///这里是要遍历所有的点,因为不一定是第0个点作为起点
            {
                if(!vis[j]&& dist[j] < minn)
                {
                    minn=dist[j];
                    mini=j;
                }
            }
            vis[mini]=true;
            for(int j=0; j<G.vexnum; j++)
            {
                if(dist[j]>dist[mini]+G.arcs[mini][j].adj)
                {
                    dist[j]=dist[mini]+G.arcs[mini][j].adj;
                    pre[j]=mini;
                }
// dist[j]=dist[j]<(dist[mini]+G.arcs[mini][j].adj)?dist[j]:(dist[mini]+G.arcs[mini][j].adj);
// printf("**%d %d\n",dist[j],dist[mini]+G.arcs[mini][j].adj);
            }
        }
        cout<<"从源点"<<G.vexs[s]<<"到达所有位置的最短路径:\n";
        for(int i=0; i<G.vexnum; i++)
        {
            if(i!=s)
            {
                cout<<"到达"<<G.vexs[i]<<"的最短路径距离:"<<dist[i]<<endl;
                int step=0,road[108],tmp=i;
                while(pre[tmp]!=tmp)///回溯寻找路径
                {
                    road[step++]=pre[tmp];
                    tmp=pre[tmp];
                }
                printf("最短路径为:");
                for(int j=step-1; j>=0; j--) cout<<G.vexs[road[j]]<<" ";
                cout<<G.vexs[i]<<endl;
            }
        }
        printf("*********输入新起点搜索起点重新遍历*********\n");
        printf("*********输入END结束最短路径计算*********\n");
        printf("请输入操作:");
    }
    printf("==============================================================\n");
    printf("|| 1.深度优先搜索遍历 ||\n");
    printf("|| 2.广度优先搜索遍历 ||\n");
    printf("|| 3.最短路径计算(仅带权图) ||\n");
    printf("|| 4.结束程序 ||\n");
    printf("|| 5.重新建图 ||\n");
    printf("==============================================================\n");
    printf("请输入对图的操作:\n");
}

邻接矩阵基本类型的定义:

typedef struct ArcCell///弧(邻接矩阵)
{
    int adj;
    InfoType *info;
} ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct///图(邻接矩阵)
{
    string vexs[MAX_VERTEX_NUM];///结点名
    AdjMatrix arcs;             ///邻接矩阵
    int vexnum,arcnum;          ///结点数,弧数
    GraphKind kind;
} MGraph;

带权无向网的建立:

Status CreateUDN(MGraph &G)///邻接矩阵(建立带权无向网)
{
    int IncInfo;
    printf("建立带权无向网,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
    scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
    {
        if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
        if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
        scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    }
    printf("请为从1至%d个结点命名:\n",G.vexnum);
    for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
    for(int i=0; i<G.vexnum; i++)
        for(int j=0; j<G.vexnum; j++)
            G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
    string v1,v2;
    printf("请输入%d组相互依附的两结点与边权(x<--->y 边权:z):\n",G.arcnum);
    int w;///边权
    for(int k=0; k<G.arcnum; k++)
    {
        cout<<"第"<<k+1<<"条边:";
        cin>>v1>>v2>>w;
        int i=LocateVex(G,v1);
        int j=LocateVex(G,v2);
        if(i==-1||j==-1||w<=0||w>1000000000)
        {
            if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
            if(w<=0||w>1000000000)printf("输入的边权错误,请重新输入\n");
            k--;
            continue;
        }
        G.arcs[i][j].adj=w;///带权
        if(IncInfo)scanf("%s",G.arcs[i][j].info);
        G.arcs[j][i]=G.arcs[i][j];///无向图,结构体赋值
    }
    return OK;
}

完整代码:

#include<iostream>
#include<stdio.h>
#include <time.h>
#include<string>
#include<stdlib.h>
#include<queue>
#include<string.h>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAX_VERTEX_NUM 105
#define INFINITY 0X3f3f3f3f
typedef char InfoType;
typedef int Status;
typedef int Boolean;
typedef string VertexType;
typedef enum {DG,DN,UDG,UDN} GraphKind;
Boolean visited[MAX_VERTEX_NUM];
typedef struct ArcCell///弧(邻接矩阵)
{
    int adj;
    InfoType *info;
} ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct///图(邻接矩阵)
{
    string vexs[MAX_VERTEX_NUM];///结点名
    AdjMatrix arcs;             ///邻接矩阵
    int vexnum,arcnum;          ///结点数,弧数
    GraphKind kind;
} MGraph;
Status (*VisitFunc)(MGraph G,int v);

Status LocateVex(MGraph G,string name)///获取结点标号
{
    for(int i=0; i<G.vexnum; i++)
        if(name==G.vexs[i])return i;
    return -1;
}

Status CreateDG(MGraph &G)///邻接矩阵(建立无权有向图)
{
    int IncInfo;
    printf("建立无权有向图,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
    scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
    {
        if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
        if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
        scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    }
    printf("请为从1至%d个结点命名:\n",G.vexnum);
    for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
    for(int i=0; i<G.vexnum; i++)
        for(int j=0; j<G.vexnum; j++)G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
    string v1,v2;
    printf("请输入%d组由左指向右的有向边(x--->y):\n",G.arcnum);
    for(int k=0; k<G.arcnum; k++)
    {
        cout<<"第"<<k+1<<"条边:";
        cin>>v1>>v2;
        int i=LocateVex(G,v1);
        int j=LocateVex(G,v2);
        if(i==-1||j==-1)
        {
            if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
            k--;
            continue;
        }
        G.arcs[i][j].adj=TRUE;///无权
        if(IncInfo)scanf("%s",G.arcs[i][j].info);
    }
    return OK;
}

Status CreateDN(MGraph &G)///邻接矩阵(建立带权有向网)
{
    int IncInfo;
    printf("建立带权有向网,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
    scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
    {
        if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
        if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
        scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    }
    printf("请为从1至%d个结点命名:\n",G.vexnum);
    for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
    for(int i=0; i<G.vexnum; i++)
        for(int j=0; j<G.vexnum; j++)G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
    string v1,v2;
    int w;
    printf("请输入%d组由左指向右的有向边与边权(x--->y 边权:z):\n",G.arcnum);
    for(int k=0; k<G.arcnum; k++)
    {
        cout<<"第"<<k+1<<"条边:";
        cin>>v1>>v2>>w;
        int i=LocateVex(G,v1);
        int j=LocateVex(G,v2);
        if(i==-1||j==-1||w<=0||w>1000000000)
        {
            if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
            if(w<=0||w>1000000000)printf("输入的边权错误,请重新输入\n");
            k--;
            continue;
        }
        G.arcs[i][j].adj=w;///带权
        if(IncInfo)scanf("%s",G.arcs[i][j].info);
    }
    return OK;
}

Status CreateUDG(MGraph &G)///邻接矩阵(建立无权无向图)
{
    int IncInfo;
    printf("建立无权无向图,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
    scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
    {
        if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
        if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
        scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    }
    printf("请为从1至%d个结点命名:\n",G.vexnum);
    for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
    for(int i=0; i<G.vexnum; i++)
        for(int j=0; j<G.vexnum; j++)G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
    string v1,v2;
    printf("请输入%d组相互依附的两结点:\n",G.arcnum);
    for(int k=0; k<G.arcnum; k++)
    {
        cout<<"第"<<k+1<<"条边:";
        cin>>v1>>v2;
        int i=LocateVex(G,v1);
        int j=LocateVex(G,v2);
        if(i==-1||j==-1)
        {
            if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
            k--;
            continue;
        }
        G.arcs[i][j].adj=TRUE;///无权
        if(IncInfo)scanf("%s",G.arcs[i][j].info);
        G.arcs[j][i]=G.arcs[i][j];///无向图,结构体赋值
    }
    return OK;
}

Status CreateUDN(MGraph &G)///邻接矩阵(建立带权无向网)
{
    int IncInfo;
    printf("建立带权无向网,请依次输入总结点数、总边数、是否包含信息(0不包含、1包含):\n");
    scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    while(G.arcnum>G.vexnum*(G.vexnum-1)/2||G.arcnum<G.vexnum-1)
    {
        if(G.arcnum>G.vexnum*(G.vexnum-1)/2)printf("边数输入错误,边数过多,超过完全图最大边数,请重新输入:\n");
        if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:\n");
        scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
    }
    printf("请为从1至%d个结点命名:\n",G.vexnum);
    for(int i=0; i<G.vexnum; i++)cin>>G.vexs[i];
    for(int i=0; i<G.vexnum; i++)
        for(int j=0; j<G.vexnum; j++)
            G.arcs[i][j].adj=INFINITY,G.arcs[i][j].info=NULL;
    string v1,v2;
    printf("请输入%d组相互依附的两结点与边权(x<--->y 边权:z):\n",G.arcnum);
    int w;///边权
    for(int k=0; k<G.arcnum; k++)
    {
        cout<<"第"<<k+1<<"条边:";
        cin>>v1>>v2>>w;
        int i=LocateVex(G,v1);
        int j=LocateVex(G,v2);
        if(i==-1||j==-1||w<=0||w>1000000000)
        {
            if(i==-1||j==-1)printf("输入的结点名不存在,请重新输入\n");
            if(w<=0||w>1000000000)printf("输入的边权错误,请重新输入\n");
            k--;
            continue;
        }
        G.arcs[i][j].adj=w;///带权
        if(IncInfo)scanf("%s",G.arcs[i][j].info);
        G.arcs[j][i]=G.arcs[i][j];///无向图,结构体赋值
    }
    return OK;
}

void DFS(MGraph G,int v)///邻接矩阵DFS
{
    visited[v]=TRUE;
    VisitFunc(G,v);
    for(int w=0; w<G.vexnum; w++)
        if(G.arcs[v][w].adj!=INFINITY&&!visited[w])DFS(G,w);
}

void DFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v))
{
    VisitFunc=Visit;
    printf("请输入深度优先搜索起始结点:\n");
    string st;
    while(cin>>st)
    {
        if(st=="END")break;
        int tmp=LocateVex(G,st);
        if(tmp==-1)
        {
            printf("输入的起点不存在,请重新输入\n");
            continue;
        }
        for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
        printf("深度优先搜索遍历序列:\n");
        DFS(G,tmp);
        for(int v=0; v<G.vexnum; v++)if(!visited[v])DFS(G,v);
        printf("\n");
        printf("*********输入新起点搜索起点重新遍历*********\n");
        printf(" **********输入END结束深度优先搜索*********\n");
        printf("请输入操作:");
    }
    printf("==============================================================\n");
    printf("|| 1.深度优先搜索遍历 ||\n");
    printf("|| 2.广度优先搜索遍历 ||\n");
    printf("|| 3.最短路径计算(仅带权图) ||\n");
    printf("|| 4.结束程序 ||\n");
    printf("|| 5.重新建图 ||\n");
    printf("==============================================================\n");
    printf("请输入对图的操作:\n");
}

void BFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v))///邻接矩阵BFS
{
    queue<int>Q;
    printf("请输入广度优先搜索起始结点:\n");
    string st;
    while(cin>>st)
    {
        if(st=="END")break;
        int temp=LocateVex(G,st);
        if(temp==-1)
        {
            printf("输入的起点不存在,请重新输入\n");
            continue;
        }
        for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
        while(!Q.empty())Q.pop();
        printf("广度优先搜索遍历序列:\n");
        Visit(G,temp);
        Q.push(temp);
        visited[temp]=TRUE;
        while(!Q.empty())
        {
            int tmp=Q.front();
            Q.pop();
            for(int w=0; w<G.vexnum; w++)
            {
                if(!visited[w]&&G.arcs[tmp][w].adj!=INFINITY)
                {
                    visited[w]=TRUE;
                    Visit(G,w);
                    Q.push(w);
                }
            }
        }
        for(int v=0; v<G.vexnum; v++)///剩余连通分量
        {
            if(!visited[v])
            {
                visited[v]=TRUE;
                Visit(G,v);
                Q.push(v);
                while(!Q.empty())
                {
                    int tmp=Q.front();
                    Q.pop();
                    for(int w=0; w<G.vexnum; w++)
                    {
                        if(!visited[w]&&G.arcs[tmp][w].adj!=INFINITY)
                        {
                            visited[w]=TRUE;
                            Visit(G,w);
                            Q.push(w);
                        }
                    }
                }
            }
        }
        printf("\n");
        printf("*********输入新起点搜索起点重新遍历*********\n");
        printf("*********输入END结束广度优先搜索*********\n");
        printf("请输入操作:");
    }
    printf("==============================================================\n");
    printf("|| 1.深度优先搜索遍历 ||\n");
    printf("|| 2.广度优先搜索遍历 ||\n");
    printf("|| 3.最短路径计算(仅带权图) ||\n");
    printf("|| 4.结束程序 ||\n");
    printf("|| 5.重新建图 ||\n");
    printf("==============================================================\n");
    printf("请输入对图的操作:\n");
}

Status CreateGraph(MGraph &G)///邻接矩阵
{
    printf("**********************************************\n");
    printf("* *\n");
    printf("* 1:无权有向图 *\n");
    printf("* 2:带权有向网 *\n");
    printf("* 3:无权无向图 *\n");
    printf("* 4:带权无向网 *\n");
    printf("* *\n");
    printf("**********************************************\n");
    printf("请输入建图类型:");
    scanf("%d",&G.kind);///输入图的种类
    system("cls");
    switch(G.kind-1)
    {
    case DG:
        return CreateDG(G);
    case DN:
        return CreateDN(G);
    case UDG:
        return CreateUDG(G);
    case UDN:
        return CreateUDN(G);
    default:
        return ERROR;
    }
}

Status visit(MGraph G,int v)///邻接矩阵遍历
{
    cout<<G.vexs[v]<<' ';
}

///===========================================================================

typedef struct ArcNode///弧(邻接表)
{
    int adjvex;             ///当前弧指向的顶点
    int info;               ///权值
    struct ArcNode *nextarc;///下一条当前顶点为出度的弧
} ArcNode;

typedef struct VNode///点(邻接表)
{
    VertexType data;///结点名
    ArcNode *firstarc;///该点的第一条出边
} VNode,AdjList[MAX_VERTEX_NUM];

typedef struct///图(邻接表)
{
    AdjList vertices;///点的邻接表(数组)
    int vexnum,arcnum;
    int kind;
} ALGraph;
Status (*VisitFunc_2)(ALGraph G,int v);

void ArcAdd_sort(ALGraph &G,int v1,int v2,int w)///从大到小顺序建立邻接表
{
    ArcNode *p,*h,*q;
    p=new ArcNode;
    p->adjvex=v2;
    p->info=w;
    p->nextarc=NULL;
    h=q=G.vertices[v1].firstarc;
    if(q==NULL)G.vertices[v2].firstarc=p;
    else
    {
        if(p->adjvex > q->adjvex)///邻接表按结点序号从大到小排列
        {
            p->nextarc=q;
            G.vertices[v2].firstarc=p;
        }
        else
        {
            while(G.vertices[v2].firstarc!=NULL&&q->nextarc!=NULL&&p->adjvex < q->adjvex)
            {
                h=q;
                q=q->nextarc;
            }
            if(q->nextarc==NULL&&p->adjvex < q->adjvex) q->nextarc=p;
            else
            {
                p->nextarc=q;
                h->nextarc=p;
            }
        }
    }
}

void ArcAdd(ALGraph &G,int v1,int v2,int w)///加边
{
    ArcNode *p,*q;
    p=new ArcNode;
    p->adjvex=v2;
    p->info=w;
    p->nextarc=NULL;
    q=G.vertices[v1].firstarc;
    if(q==NULL) G.vertices[v1].firstarc=p;///若第一条依附v2顶点的弧还未存在,新加入的边作为第一条依附弧
    else///否则顺着链表向后查找
    {
        while(q->nextarc!=NULL) q=q->nextarc;
        q->nextarc=p;
    }
}

int LocateVex_2(ALGraph G,string name)///获取结点标号
{
    for(int i=0; i<G.vexnum; i++)
        if(name==G.vertices[i].data)return i;
    return -1;
}

Status CreateDG_2(ALGraph &G)///邻接表(建立无权有向图)
{
    printf("建立无权有向图,请依次输入总结点数、总边数:\n");
    scanf("%d%d",&G.vexnum,&G.arcnum);
    printf("请为从1至n个结点命名:\n");
    for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
    string v1,v2;
    printf("请输入%d组由左指向右的有向边:\n",G.arcnum);
    for(int k=0; k<G.arcnum; k++)
    {
        cin>>v1>>v2;
        int i=LocateVex_2(G,v1);///获取标号
        int j=LocateVex_2(G,v2);
        ArcAdd(G,i,j,1);
    }
    return OK;
}

Status CreateDN_2(ALGraph &G)///邻接表(建立带权有向网)
{
    printf("建立带权有向网,请依次输入总结点数、总边数:\n");
    scanf("%d%d",&G.vexnum,&G.arcnum);
    printf("请为从1至n个结点命名:\n");
    for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
    string v1,v2;
    int w;
    printf("请输入%d组由左指向右的有向边与边权:\n",G.arcnum);
    for(int k=0; k<G.arcnum; k++)
    {
        cin>>v1>>v2>>w;
        int i=LocateVex_2(G,v1);///获取标号
        int j=LocateVex_2(G,v2);
        ArcAdd(G,i,j,w);
    }
    return OK;
}

Status CreateUDG_2(ALGraph &G)///邻接表(建立无权无向图)
{
    printf("建立无权无向图,请依次输入总结点数、总边数:\n");
    scanf("%d%d",&G.vexnum,&G.arcnum);
    printf("请为从1至n个结点命名:\n");
    for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
    string v1,v2;
    printf("请输入%d组相互依附的两结点:\n",G.arcnum);
    for(int k=0; k<G.arcnum; k++)
    {
        cin>>v1>>v2;
        int i=LocateVex_2(G,v1);///获取标号
        int j=LocateVex_2(G,v2);
        ArcAdd(G,i,j,1);///无向边
        ArcAdd(G,j,i,1);
    }
    return OK;
}

Status CreateUDN_2(ALGraph &G)///邻接表(建立带权无向网)
{
    printf("建立带权无向网,请依次输入总结点数、总边数:\n");
    scanf("%d%d",&G.vexnum,&G.arcnum);
    printf("请为从1至%d个结点命名:\n",G.vexnum);
    for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
    string v1,v2;
    int w;
    printf("请输入%d组相互依附的两结点与边权:\n",G.arcnum);
    for(int k=0; k<G.arcnum; k++)
    {
        cin>>v1>>v2>>w;
        int i=LocateVex_2(G,v1);///获取标号
        int j=LocateVex_2(G,v2);
        ArcAdd(G,i,j,w);///无向边
        ArcAdd(G,j,i,w);
    }
    return OK;
}

int FirstAdjVex(ALGraph G,int v)
{
    if(G.vertices[v].firstarc) return G.vertices[v].firstarc->adjvex;
    return -1;
}
int NextAdjVex(ALGraph G,int v,int w)
{
    ArcNode *p=G.vertices[v].firstarc;
    while(p->adjvex!=w&&p->nextarc!=NULL)p=p->nextarc;
    if(p->nextarc==NULL)return -1;
    return p->nextarc->adjvex;
}

void DFS_2(ALGraph G,int v)///邻接表DFS
{
    visited[v]=TRUE;
    VisitFunc_2(G,v);
    for(int w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v,w))
        if(!visited[w])DFS_2(G,w);
}

void DFSTraverse_2(ALGraph G,Status (*Visit)(ALGraph G,int v))
{
    VisitFunc_2=Visit;
    printf("请输入深度优先搜索起始结点:\n");
    for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
    string st;
    cin>>st;
    int tmp=LocateVex_2(G,st);
    printf("深度优先搜索遍历序列:\n");
    DFS_2(G,tmp);
    for(int v=0; v<G.vexnum; v++)if(!visited[v])DFS_2(G,v);
    printf("\n");
}

void BFSTraverse_2(ALGraph G,Status (*Visit)(ALGraph G,int v))///邻接表BFS
{
    for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
    queue<int>Q;
    printf("请输入广度优先搜索起始结点:\n");
    string st;
    cin>>st;
    printf("广度优先搜索遍历序列:\n");
    int temp=LocateVex_2(G,st);
    Visit(G,temp);
    Q.push(temp);
    visited[temp]=TRUE;
    while(!Q.empty())
    {
        int tmp=Q.front();
        Q.pop();
        for(int w=FirstAdjVex(G,tmp); w>=0; w=NextAdjVex(G,tmp,w))
        {
            if(!visited[w])
            {
                visited[w]=TRUE;
                Visit(G,w);
                Q.push(w);
            }
        }
    }
    for(int v=0; v<G.vexnum; v++)///剩余连通分量
    {
        if(!visited[v])
        {
            visited[v]=TRUE;
            Visit(G,v);
            Q.push(v);
            while(!Q.empty())
            {
                int tmp=Q.front();
                Q.pop();
                for(int w=FirstAdjVex(G,tmp); w>=0; w=NextAdjVex(G,tmp,w))
                {
                    if(!visited[w])
                    {
                        visited[w]=TRUE;
                        Visit(G,w);
                        Q.push(w);
                    }
                }
            }
        }
    }
    printf("\n");
}

void PrintGraph(ALGraph G)///输出邻接表
{
    cout<<"图的创建完成,该图的邻接表表示为:"<<endl;
    ArcNode *p;
    for(int i=0; i<G.vexnum; i++)
    {
        if(G.vertices[i].firstarc == NULL)
            cout<<i<<":"<<G.vertices[i].data<<"-->NULL"<<endl;
        else
        {
            p = G.vertices[i].firstarc;
            cout<<i<<":"<<G.vertices[i].data<<"-->";
            while(p->nextarc!=NULL)
            {
                cout<<p->adjvex<<"-->";
                p = p->nextarc;
            }
            cout<<p->adjvex<<"-->NULL"<<endl;
        }
    }
}

Status CreateGraph_2(ALGraph &G)///邻接表
{
    printf("**********************************************\n");
    printf("* *\n");
    printf("* 1:无权有向图 *\n");
    printf("* 2:带权有向网 *\n");
    printf("* 3:无权无向图 *\n");
    printf("* 4:带权无向网 *\n");
    printf("* *\n");
    printf("**********************************************\n");
    printf("请输入建图类型:");
    scanf("%d",&G.kind);///输入图的种类
    system("cls");
    switch(G.kind-1)
    {
    case DG:
        return CreateDG_2(G);
    case DN:
        return CreateDN_2(G);
    case UDG:
        return CreateUDG_2(G);
    case UDN:
        return CreateUDN_2(G);
    default:
        return ERROR;
    }
}
Status visit_2(ALGraph G,int v)///邻接表遍历
{
    cout<<G.vertices[v].data<<' ';
}

///===============================================================================
void dijkstra(MGraph G)
{
    string tmp;
    int pre[108];
    int dist[MAX_VERTEX_NUM],s;///最短路数组
    bool vis[MAX_VERTEX_NUM];
    printf("请输入该图起点:");
    while(cin>>tmp)///最短路源点
    {
        if(tmp=="END")break;
        s=LocateVex(G,tmp);
        if(s==-1)
        {
            printf("输入的起点不存在,请重新输入\n");
            continue;
        }
        for(int i=0; i<G.vexnum; i++)pre[i]=s;///路径父亲初始化
        memset(vis,false,sizeof(vis));
        memset(dist,0x3f,sizeof(dist));
        for(int i=0; i<G.vexnum; i++)///所有点到达起点的距离
            dist[i]=G.arcs[s][i].adj;
        dist[s]=0;///标记起点长度为0
        vis[s]=true;///标记走过
        for(int i=1; i<G.vexnum; i++)///遍历n-1次
        {
            int minn=0x7fffffff,mini;
            for(int j=0; j<G.vexnum; j++)///这里是要遍历所有的点,因为不一定是第0个点作为起点
            {
                if(!vis[j]&& dist[j] < minn)
                {
                    minn=dist[j];
                    mini=j;
                }
            }
            vis[mini]=true;
            for(int j=0; j<G.vexnum; j++)
            {
                if(dist[j]>dist[mini]+G.arcs[mini][j].adj)
                {
                    dist[j]=dist[mini]+G.arcs[mini][j].adj;
                    pre[j]=mini;
                }
// dist[j]=dist[j]<(dist[mini]+G.arcs[mini][j].adj)?dist[j]:(dist[mini]+G.arcs[mini][j].adj);
// printf("**%d %d\n",dist[j],dist[mini]+G.arcs[mini][j].adj);
            }
        }
        cout<<"从源点"<<G.vexs[s]<<"到达所有位置的最短路径:\n";
        for(int i=0; i<G.vexnum; i++)
        {
            if(i!=s)
            {
                cout<<"到达"<<G.vexs[i]<<"的最短路径距离:"<<dist[i]<<endl;
                int step=0,road[108],tmp=i;
                while(pre[tmp]!=tmp)
                {
                    road[step++]=pre[tmp];
                    tmp=pre[tmp];
                }
                printf("最短路径为:");
                for(int j=step-1; j>=0; j--) cout<<G.vexs[road[j]]<<" ";
                cout<<G.vexs[i]<<endl;
            }
        }
        printf("*********输入新起点搜索起点重新遍历*********\n");
        printf("*********输入END结束最短路径计算*********\n");
        printf("请输入操作:");
    }
    printf("==============================================================\n");
    printf("|| 1.深度优先搜索遍历 ||\n");
    printf("|| 2.广度优先搜索遍历 ||\n");
    printf("|| 3.最短路径计算(仅带权图) ||\n");
    printf("|| 4.结束程序 ||\n");
    printf("|| 5.重新建图 ||\n");
    printf("==============================================================\n");
    printf("请输入对图的操作:\n");
}
int main()
{
    while(true)
    {
        MGraph G1;
        while(!CreateGraph(G1))///邻接矩阵
            printf("输入错误\n");
// for(int i=0; i<G1.vexnum; i++)
// for(int j=0; j<G1.vexnum; j++)
// printf("%15d%c",G1.arcs[i][j].adj,j==G1.vexnum-1?'\n':' ');
        int con;
        printf("==============================================================\n");
        printf("|| 1.深度优先搜索遍历 ||\n");
        printf("|| 2.广度优先搜索遍历 ||\n");
        printf("|| 3.最短路径计算(仅带权图) ||\n");
        printf("|| 4.结束程序 ||\n");
        printf("|| 5.重新建图 ||\n");
        printf("==============================================================\n");
        printf("请输入对图的操作:\n");
        while(scanf("%d",&con)!=EOF)
        {
            system("cls");
            if(con==1)
                DFSTraverse(G1,visit);///深搜邻接矩阵
            else if(con==2)
                BFSTraverse(G1,visit);///广搜邻接矩阵
            else if(con==3&&(G1.kind==2||G1.kind==4))
                dijkstra(G1);
            else if(con==4)
                return 0;
            else if(con==5)
                break;
            else
                printf("输入错误,可能输入错误的指令或对无权图求最短路\n");
        }
        printf("请重新建图!\n");
//// ALGraph G2;///邻接表
// CreateGraph_2(G2);
// PrintGraph(G2);///输出邻接表
// DFSTraverse_2(G2,visit_2);///邻接表深搜
// BFSTraverse_2(G2,visit_2);///邻接表广搜
    }
}
/* 3 8 9 V1 V2 V3 V4 V5 V6 V7 V8 V1 V2 V2 V4 V4 V8 V8 V5 V2 V5 V1 V3 V3 V6 V3 V7 V6 V7 V1 V2 1 V1 V3 12 V2 V3 9 V2 V4 3 V3 V5 5 V4 V3 4 V4 V5 13 V4 V6 15 V5 V6 4 */
    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/kuronekonano/article/details/79676229
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞