第十一周项目四C/C++利用遍历思想求解图问题

来源:互联网 发布:战国之怒进阶数据 编辑:程序博客网 时间:2024/06/03 12:47
/*   *Copyright (c) 2017,烟台大学计算机与控制工程学院   *All rights reserved.   *文件名称:.cpp*完成日期:2017年11月23日   *版 本 号:v1.0   * 利用遍历思想求解图问题 /* 

假设图G采用邻接表存储,分别设计实现以下要求的算法,要求用区别于示例中的图进行多次测试,通过观察输出值,掌握相关问题的处理方法。 
  (1)设计一个算法,判断顶点u到v是否有简单路径 
  (2)设计一个算法输出图G中从顶点u到v的一条简单路径(设计测试图时,保证图G中从顶点u到v至少有一条简单路径)。 
  (3)输出从顶点u到v的所有简单路径。 
  (4)输出图G中从顶点u到v的长度为s的所有简单路径。 
  (5)求图中通过某顶点k的所有简单回路(若存在)

      (6)求不带权连通图G中从顶点u到顶点v的一条最短路径。 

  (7)求不带权连通图G中,距离顶点v最远的顶点k 

解答:

1、是否有简单路径? 
问题:假设图G采用邻接表存储,设计一个算法,判断顶点u到v是否有简单路径。

#include <stdio.h>#include <malloc.h>#include "graph.h"int visited[MAXV];     //定义存放节点的访问标志的全局数组void ExistPath(ALGraph *G,int u,int v, bool &has){    int w;    ArcNode *p;    visited[u]=1;    if(u==v)    {        has=true;        return;    }    p=G->adjlist[u].firstarc;    while (p!=NULL)    {        w=p->adjvex;        if (visited[w]==0)            ExistPath(G,w,v,has);        p=p->nextarc;    }}void HasPath(ALGraph *G,int u,int v){    int i;    bool flag = false;    for (i=0; i<G->n; i++)        visited[i]=0; //访问标志数组初始化    ExistPath(G,u,v,flag);    printf(" 从 %d 到 %d ", u, v);    if(flag)        printf("有简单路径\n");    else        printf("无简单路径\n");}int main(){    ALGraph *G;    int A[5][5]=    {        {0,0,0,0,0},        {0,0,1,0,0},        {0,0,0,1,1},        {0,0,0,0,0},        {1,0,0,1,0},    };  //请画出对应的有向图    ArrayToList(A[0], 5, G);    HasPath(G, 1, 0);    HasPath(G, 4, 1);    return 0;}
附:测试图结构及存储 


运行结果:


2、输出简单路径 
问题:假设图G采用邻接表存储,设计一个算法输出图G中从顶点u到v的一条简单路径(假设图G中从顶点u到v至少有一条简单路径)。

#include <stdio.h>#include <malloc.h>#include "graph.h"int visited[MAXV];     //定义存放节点的访问标志的全局数组void FindAPath(ALGraph *G,int u,int v,int path[],int d){    //d表示path中的路径长度,初始为-1    int w,i;    ArcNode *p;    visited[u]=1;    d++;    path[d]=u;  //路径长度d增1,顶点u加入到路径中    if (u==v)   //找到一条路径后输出并返回    {        printf("一条简单路径为:");        for (i=0; i<=d; i++)            printf("%d ",path[i]);        printf("\n");        return;         //找到一条路径后返回    }    p=G->adjlist[u].firstarc;  //p指向顶点u的第一个相邻点    while (p!=NULL)    {        w=p->adjvex;    //相邻点的编号为w        if (visited[w]==0)            FindAPath(G,w,v,path,d);        p=p->nextarc;   //p指向顶点u的下一个相邻点    }}void APath(ALGraph *G,int u,int v){    int i;    int path[MAXV];    for (i=0; i<G->n; i++)        visited[i]=0; //访问标志数组初始化    FindAPath(G,u,v,path,-1);  //d初值为-1,调用时d++,即变成了0}int main(){    ALGraph *G;    int A[5][5]=    {        {0,0,0,0,0},        {0,0,1,0,0},        {0,0,0,1,1},        {0,0,0,0,0},        {1,0,0,1,0},    };  //请画出对应的有向图    ArrayToList(A[0], 5, G);    APath(G, 1, 0);    APath(G, 4, 1);    return 0;}
运行结果:


3、输出所有路径 
问题:输出从顶点u到v的所有简单路径。

#include <stdio.h>#include <malloc.h>#include "graph.h"int visited[MAXV];     //定义存放节点的访问标志的全局数组void FindPaths(ALGraph *G,int u,int v,int path[],int d)//d是到当前为止已走过的路径长度,调用时初值为-1{    int w,i;    ArcNode *p;    visited[u]=1;    d++;            //路径长度增1    path[d]=u;              //将当前顶点添加到路径中    if (u==v && d>1)            //输出一条路径    {        printf("  ");        for (i=0; i<=d; i++)            printf("%d ",path[i]);        printf("\n");    }    p=G->adjlist[u].firstarc; //p指向u的第一条边    while(p!=NULL)    {        w=p->adjvex;     //w为u的邻接顶点        if (visited[w]==0)      //若顶点未标记访问,则递归访问之            FindPaths(G,w,v,path,d);        p=p->nextarc; //找u的下一个邻接顶点    }    visited[u]=0;   //恢复环境}void DispPaths(ALGraph *G,int u,int v){    int i;    int path[MAXV];    for (i=0; i<G->n; i++)        visited[i]=0; //访问标志数组初始化    printf("从%d到%d的所有路径:\n",u,v);    FindPaths(G,u,v,path,-1);    printf("\n");}int main(){    ALGraph *G;    int A[5][5]=    {        {0,1,0,1,0},        {1,0,1,0,0},        {0,1,0,1,1},        {1,0,1,0,1},        {0,0,1,1,0}    };  //请画出对应的有向图    ArrayToList(A[0], 5, G);    DispPaths(G, 1, 4);    return 0;}
附:测试用的图结构、存储结构、运行结果 

运行结果:


4、输出一些简单回路 
问题:输出图G中从顶点u到v的长度为s的所有简单路径。

#include <stdio.h>#include <malloc.h>#include "graph.h"int visited[MAXV];     //定义存放节点的访问标志的全局数组void SomePaths(ALGraph *G,int u,int v,int s, int path[],int d)//d是到当前为止已走过的路径长度,调用时初值为-1{    int w,i;    ArcNode *p;    visited[u]=1;    d++;            //路径长度增1    path[d]=u;              //将当前顶点添加到路径中    if (u==v && d==s)           //输出一条路径    {        printf("  ");        for (i=0; i<=d; i++)            printf("%d ",path[i]);        printf("\n");    }    p=G->adjlist[u].firstarc; //p指向u的第一条边    while(p!=NULL)    {        w=p->adjvex;     //w为u的邻接顶点        if (visited[w]==0)      //若顶点未标记访问,则递归访问之            SomePaths(G,w,v,s,path,d);        p=p->nextarc; //找u的下一个邻接顶点    }    visited[u]=0;   //恢复环境}void DispSomePaths(ALGraph *G,int u,int v, int s){    int i;    int path[MAXV];    for (i=0; i<G->n; i++)        visited[i]=0; //访问标志数组初始化    printf("从%d到%d长为%d的路径:\n",u,v,s);    SomePaths(G,u,v,s,path,-1);    printf("\n");}int main(){    ALGraph *G;    int A[5][5]=    {        {0,1,0,1,0},        {1,0,1,0,0},        {0,1,0,1,1},        {1,0,1,0,1},        {0,0,1,1,0}    };  //请画出对应的有向图    ArrayToList(A[0], 5, G);    DispSomePaths(G, 1, 4, 3);    return 0;}
附:测试的图结构、运行结果 

运行结果:


5、输出通过一个节点的所有简单回路 
问题:求图中通过某顶点k的所有简单回路(若存在)

#include <stdio.h>#include <malloc.h>#include "graph.h"int visited[MAXV];       //全局变量void DFSPath(ALGraph *G,int u,int v,int path[],int d)//d是到当前为止已走过的路径长度,调用时初值为-1{    int w,i;    ArcNode *p;    visited[u]=1;    d++;    path[d]=u;    p=G->adjlist[u].firstarc;   //p指向顶点u的第一条边    while (p!=NULL)    {        w=p->adjvex;            //w为顶点u的相邻点        if (w==v && d>0)        //找到一个回路,输出之        {            printf("  ");            for (i=0; i<=d; i++)                printf("%d ",path[i]);            printf("%d \n",v);        }        if (visited[w]==0)          //w未访问,则递归访问之            DFSPath(G,w,v,path,d);        p=p->nextarc;       //找u的下一个邻接顶点    }    visited[u]=0;           //恢复环境:使该顶点可重新使用}void FindCyclePath(ALGraph *G,int k)//输出经过顶点k的所有回路{    int path[MAXV],i;    for (i=0; i<G->n; i++)        visited[i]=0; //访问标志数组初始化    printf("经过顶点%d的所有回路\n",k);    DFSPath(G,k,k,path,-1);    printf("\n");}int main(){    ALGraph *G;    int A[5][5]=    {        {0,1,1,0,0},        {0,0,1,0,0},        {0,0,0,1,1},        {0,0,0,0,1},        {1,0,0,0,0}    };  //请画出对应的有向图    ArrayToList(A[0], 5, G);    FindCyclePath(G, 0);    return 0;}
附:测试用图结构、输出结果 


运行结果:


6,最短路径 
问题:求不带权连通图G中从顶点u到顶点v的一条最短路径。

#include <stdio.h>#include <malloc.h>#include "graph.h"typedef struct{    int data;                   //顶点编号    int parent;                 //前一个顶点的位置} QUERE;                        //非环形队列类型void ShortPath(ALGraph *G,int u,int v){    //输出从顶点u到顶点v的最短逆路径    ArcNode *p;    int w,i;    QUERE qu[MAXV];             //非环形队列    int front=-1,rear=-1;       //队列的头、尾指针    int visited[MAXV];    for (i=0; i<G->n; i++)      //访问标记置初值0        visited[i]=0;    rear++;                     //顶点u进队    qu[rear].data=u;    qu[rear].parent=-1;    visited[u]=1;    while (front!=rear)         //队不空循环    {        front++;                //出队顶点w        w=qu[front].data;        if (w==v)               //找到v时输出路径之逆并退出        {            i=front;            //通过队列输出逆路径            while (qu[i].parent!=-1)            {                printf("%2d ",qu[i].data);                i=qu[i].parent;            }            printf("%2d\n",qu[i].data);            break;        }        p=G->adjlist[w].firstarc;   //找w的第一个邻接点        while (p!=NULL)        {            if (visited[p->adjvex]==0)            {                visited[p->adjvex]=1;                rear++;             //将w的未访问过的邻接点进队                qu[rear].data=p->adjvex;                qu[rear].parent=front;            }            p=p->nextarc;           //找w的下一个邻接点        }    }}int main(){    ALGraph *G;    int A[9][9]=    {        {0,1,1,0,0,0,0,0,0},        {0,0,0,1,1,0,0,0,0},        {0,0,0,0,1,1,0,0,0},        {0,0,0,0,0,0,1,0,0},        {0,0,0,0,0,1,1,0,0},        {0,0,0,0,0,0,0,1,0},        {0,0,0,0,0,0,0,1,1},        {0,0,0,0,0,0,0,0,1},        {0,0,0,0,0,0,0,0,0}    };  //请画出对应的有向图    ArrayToList(A[0], 9, G);    ShortPath(G,0,7);    return 0;}
运行结果:


附:测试用图结构 


7、最远顶点 
问题:求不带权连通图G中,距离顶点v最远的顶点k

#include <stdio.h>#include <malloc.h>#include "graph.h"int Maxdist(ALGraph *G,int v){    ArcNode *p;    int i,j,k;    int Qu[MAXV];               //环形队列    int visited[MAXV];              //访问标记数组    int front=0,rear=0;             //队列的头、尾指针    for (i=0; i<G->n; i++)          //初始化访问标志数组        visited[i]=0;    rear++;    Qu[rear]=v;                 //顶点v进队    visited[v]=1;               //标记v已访问    while (rear!=front)    {        front=(front+1)%MAXV;        k=Qu[front];                //顶点k出队        p=G->adjlist[k].firstarc;       //找第一个邻接点        while (p!=NULL)             //所有未访问过的相邻点进队        {            j=p->adjvex;            //邻接点为顶点j            if (visited[j]==0)          //若j未访问过            {                visited[j]=1;                rear=(rear+1)%MAXV;                Qu[rear]=j; //进队            }            p=p->nextarc;           //找下一个邻接点        }    }    return k;}int main(){    ALGraph *G;    int A[9][9]=    {        {0,1,1,0,0,0,0,0,0},        {0,0,0,1,1,0,0,0,0},        {0,0,0,0,1,1,0,0,0},        {0,0,0,0,0,0,1,0,0},        {0,0,0,0,0,1,1,0,0},        {0,0,0,0,0,0,0,1,0},        {0,0,0,0,0,0,0,1,1},        {0,0,0,0,0,0,0,0,1},        {0,0,0,0,0,0,0,0,0}    };  //请画出对应的有向图    ArrayToList(A[0], 9, G);    printf("离顶点0最远的顶点:%d",Maxdist(G,0));    return 0;}
附:测试用图结构 



运行结果:


阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 驾照的分扣完了怎么办 驾照被扣了3分怎么办 交警扣了行驶证怎么办 报考驾照时手机号录错怎么办 摩托车被交警队拖走怎么办 汽车牌照被偷了怎么办 代理品牌个体工商营业证怎么办 2地交社保怎么办退休 驾驶证脱审3月怎么办 a1一次性扣12分怎么办 驾照在外地掉了怎么办 在外市考的驾照怎么办 驾照过期3个月怎么办 驾照过期6个月怎么办 b本扣分了6分怎么办 b2驾照提前换证有扣分怎么办 酒驾驾驶证被扣怎么办 驾驶证被扣了分怎么办 c1驾照扣了12分怎么办 结婚证丢了怎么办离婚手续 结婚证不见了怎么办离婚手续 科目一身份丢了怎么办 考驾照身份证过期了怎么办 酒驾发交通事故致人死亡怎么办 车保险快到期了怎么办 车保险贴掉了怎么办 小车撞凹进去了怎么办 被代位追偿了怎么办 车被别人抵押了怎么办 朋友没驾照借车怎么办 车子被朋友撞了怎么办 电车被交警扣了怎么办 e照扣了12分怎么办 驾驶证被扣33分怎么办 a2驾驶员扣33分怎么办 驾驶证被扣48分怎么办 驾照扣了33分怎么办 车辆被扣36分怎么办 车被朋友借走了怎么办 在中国终身禁驾怎么办 c驾驶证忘年审了怎么办