zoukankan      html  css  js  c++  java
  • 数据结构课程设计——图的建立和遍历(邻接矩阵+邻接表)和最短路径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("输入的起点不存在,请重新输入
    ");
                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
    ",dist[j],dist[mini]+G.arcs[mini][j].adj);
                }
            }
            cout<<"从源点"<<G.vexs[s]<<"到达所有位置的最短路径:
    ";
            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("*********输入新起点搜索起点重新遍历*********
    ");
            printf("*********输入END结束最短路径计算*********
    ");
            printf("请输入操作:");
        }
        printf("==============================================================
    ");
        printf("||                     1.深度优先搜索遍历                   ||
    ");
        printf("||                     2.广度优先搜索遍历                   ||
    ");
        printf("||                     3.最短路径计算(仅带权图)             ||
    ");
        printf("||                     4.结束程序                           ||
    ");
        printf("||                     5.重新建图                           ||
    ");
        printf("==============================================================
    ");
        printf("请输入对图的操作:
    ");
    }

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

    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包含):
    ");
        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("边数输入错误,边数过多,超过完全图最大边数,请重新输入:
    ");
            if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:
    ");
            scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
        }
        printf("请为从1至%d个结点命名:
    ",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):
    ",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("输入的结点名不存在,请重新输入
    ");
                if(w<=0||w>1000000000)printf("输入的边权错误,请重新输入
    ");
                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包含):
    ");
        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("边数输入错误,边数过多,超过完全图最大边数,请重新输入:
    ");
            if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:
    ");
            scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
        }
        printf("请为从1至%d个结点命名:
    ",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):
    ",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("输入的结点名不存在,请重新输入
    ");
                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包含):
    ");
        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("边数输入错误,边数过多,超过完全图最大边数,请重新输入:
    ");
            if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:
    ");
            scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
        }
        printf("请为从1至%d个结点命名:
    ",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):
    ",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("输入的结点名不存在,请重新输入
    ");
                if(w<=0||w>1000000000)printf("输入的边权错误,请重新输入
    ");
                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包含):
    ");
        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("边数输入错误,边数过多,超过完全图最大边数,请重新输入:
    ");
            if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:
    ");
            scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
        }
        printf("请为从1至%d个结点命名:
    ",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组相互依附的两结点:
    ",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("输入的结点名不存在,请重新输入
    ");
                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包含):
    ");
        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("边数输入错误,边数过多,超过完全图最大边数,请重新输入:
    ");
            if(G.arcnum<G.vexnum-1)printf("边数输入错误,边数不足以形成连通图,请重新输入:
    ");
            scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
        }
        printf("请为从1至%d个结点命名:
    ",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):
    ",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("输入的结点名不存在,请重新输入
    ");
                if(w<=0||w>1000000000)printf("输入的边权错误,请重新输入
    ");
                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("请输入深度优先搜索起始结点:
    ");
        string st;
        while(cin>>st)
        {
            if(st=="END")break;
            int tmp=LocateVex(G,st);
            if(tmp==-1)
            {
                printf("输入的起点不存在,请重新输入
    ");
                continue;
            }
            for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
            printf("深度优先搜索遍历序列:
    ");
            DFS(G,tmp);
            for(int v=0; v<G.vexnum; v++)if(!visited[v])DFS(G,v);
            printf("
    ");
            printf("*********输入新起点搜索起点重新遍历*********
    ");
            printf(" **********输入END结束深度优先搜索*********
    ");
            printf("请输入操作:");
        }
        printf("==============================================================
    ");
        printf("||                     1.深度优先搜索遍历                   ||
    ");
        printf("||                     2.广度优先搜索遍历                   ||
    ");
        printf("||                     3.最短路径计算(仅带权图)             ||
    ");
        printf("||                     4.结束程序                           ||
    ");
        printf("||                     5.重新建图                           ||
    ");
        printf("==============================================================
    ");
        printf("请输入对图的操作:
    ");
    }
    
    void BFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v))///邻接矩阵BFS
    {
        queue<int>Q;
        printf("请输入广度优先搜索起始结点:
    ");
        string st;
        while(cin>>st)
        {
            if(st=="END")break;
            int temp=LocateVex(G,st);
            if(temp==-1)
            {
                printf("输入的起点不存在,请重新输入
    ");
                continue;
            }
            for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
            while(!Q.empty())Q.pop();
            printf("广度优先搜索遍历序列:
    ");
            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("
    ");
            printf("*********输入新起点搜索起点重新遍历*********
    ");
            printf("*********输入END结束广度优先搜索*********
    ");
            printf("请输入操作:");
        }
        printf("==============================================================
    ");
        printf("||                     1.深度优先搜索遍历                   ||
    ");
        printf("||                     2.广度优先搜索遍历                   ||
    ");
        printf("||                     3.最短路径计算(仅带权图)             ||
    ");
        printf("||                     4.结束程序                           ||
    ");
        printf("||                     5.重新建图                           ||
    ");
        printf("==============================================================
    ");
        printf("请输入对图的操作:
    ");
    }
    
    Status CreateGraph(MGraph &G)///邻接矩阵
    {
        printf("**********************************************
    ");
        printf("*                                            *
    ");
        printf("*                1:无权有向图                *
    ");
        printf("*                2:带权有向网                *
    ");
        printf("*                3:无权无向图                *
    ");
        printf("*                4:带权无向网                *
    ");
        printf("*                                            *
    ");
        printf("**********************************************
    ");
        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("建立无权有向图,请依次输入总结点数、总边数:
    ");
        scanf("%d%d",&G.vexnum,&G.arcnum);
        printf("请为从1至n个结点命名:
    ");
        for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
        string v1,v2;
        printf("请输入%d组由左指向右的有向边:
    ",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("建立带权有向网,请依次输入总结点数、总边数:
    ");
        scanf("%d%d",&G.vexnum,&G.arcnum);
        printf("请为从1至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组由左指向右的有向边与边权:
    ",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("建立无权无向图,请依次输入总结点数、总边数:
    ");
        scanf("%d%d",&G.vexnum,&G.arcnum);
        printf("请为从1至n个结点命名:
    ");
        for(int i=0; i<G.vexnum; i++)cin>>G.vertices[i].data,G.vertices[i].firstarc=NULL;
        string v1,v2;
        printf("请输入%d组相互依附的两结点:
    ",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("建立带权无向网,请依次输入总结点数、总边数:
    ");
        scanf("%d%d",&G.vexnum,&G.arcnum);
        printf("请为从1至%d个结点命名:
    ",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组相互依附的两结点与边权:
    ",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("请输入深度优先搜索起始结点:
    ");
        for(int v=0; v<G.vexnum; v++)visited[v]=FALSE;
        string st;
        cin>>st;
        int tmp=LocateVex_2(G,st);
        printf("深度优先搜索遍历序列:
    ");
        DFS_2(G,tmp);
        for(int v=0; v<G.vexnum; v++)if(!visited[v])DFS_2(G,v);
        printf("
    ");
    }
    
    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("请输入广度优先搜索起始结点:
    ");
        string st;
        cin>>st;
        printf("广度优先搜索遍历序列:
    ");
        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("
    ");
    }
    
    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("**********************************************
    ");
        printf("*                                            *
    ");
        printf("*                1:无权有向图                *
    ");
        printf("*                2:带权有向网                *
    ");
        printf("*                3:无权无向图                *
    ");
        printf("*                4:带权无向网                *
    ");
        printf("*                                            *
    ");
        printf("**********************************************
    ");
        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("输入的起点不存在,请重新输入
    ");
                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
    ",dist[j],dist[mini]+G.arcs[mini][j].adj);
                }
            }
            cout<<"从源点"<<G.vexs[s]<<"到达所有位置的最短路径:
    ";
            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("*********输入新起点搜索起点重新遍历*********
    ");
            printf("*********输入END结束最短路径计算*********
    ");
            printf("请输入操作:");
        }
        printf("==============================================================
    ");
        printf("||                     1.深度优先搜索遍历                   ||
    ");
        printf("||                     2.广度优先搜索遍历                   ||
    ");
        printf("||                     3.最短路径计算(仅带权图)             ||
    ");
        printf("||                     4.结束程序                           ||
    ");
        printf("||                     5.重新建图                           ||
    ");
        printf("==============================================================
    ");
        printf("请输入对图的操作:
    ");
    }
    int main()
    {
        while(true)
        {
            MGraph G1;
            while(!CreateGraph(G1))///邻接矩阵
                printf("输入错误
    ");
    //        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?'
    ':' ');
            int con;
            printf("==============================================================
    ");
            printf("||                     1.深度优先搜索遍历                   ||
    ");
            printf("||                     2.广度优先搜索遍历                   ||
    ");
            printf("||                     3.最短路径计算(仅带权图)             ||
    ");
            printf("||                     4.结束程序                           ||
    ");
            printf("||                     5.重新建图                           ||
    ");
            printf("==============================================================
    ");
            printf("请输入对图的操作:
    ");
            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("输入错误,可能输入错误的指令或对无权图求最短路
    ");
            }
            printf("请重新建图!
    ");
    ////        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
    
    */
    
  • 相关阅读:
    立 Flag
    ASP.NET Core 3.0 一个 jwt 的轻量角色/用户、单个API控制的授权认证库
    C# Xamarin 数据绑定入门基础
    C# HttpClient 请求认证、数据传输笔记
    【PHP篇】输出方法
    【PHP篇】变量与常量
    C语言小笔记
    树莓派GPIO口的使用
    树莓派连接不上WiFi
    OLED屏幕详细使用(CC2530 & 51)
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135825.html
Copyright © 2011-2022 走看看