第十二周项目4—利用遍历思想求解图问题

来源:互联网 发布:腾讯云服务器绑定域名 编辑:程序博客网 时间:2024/05/16 03:16
 copyright (c) 2016,烟台大学计算机学院 
 All rights reserved. 
 文件名称:1.cpp 
 作者:孟令康
 完成日期:2016年9月12日 
 版本号:v1.0 
 问题描述: 假设图G采用邻接表存储,分别设计实现以下要求的算法,要求用区别于示例中的图进行多次测试,通过观察输出值,掌握相关问题的处理方法。   
       (1)设计一个算法,判断顶点u到v是否有简单路径   
       (2)设计一个算法输出图G中从顶点u到v的一条简单路径(设计测试图时,保证图G中从顶点u到v至少有一条简单路径)。   
       (3)输出从顶点u到v的所有简单路径。   
       (4)输出图G中从顶点u到v的长度为s的所有简单路径。   
       (5)求图中通过某顶点k的所有简单回路(若存在)    
 输入描述:若干测试数据。  

 程序输出:相应的数据输出。 

代码

1
u
v
1
u
v
1
u
v
1
u
v
(1)设计一个算法,判断顶点u到v是否有简单路径

main.cpp:

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;    }  

源代码:

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");    }  

运行结果:


(2)设计一个算法输出图G中从顶点u到v的一条简单路径(设计测试图时,保证图G中从顶点u到v至少有一条简单路径)。

main.cpp:

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;    }    
源代码:

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    }    

运行结果:


(3)输出从顶点u到v的所有简单路径。

main.cpp:

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;    }    

源代码:

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");    }    
运行结果:



(4)输出图G中从顶点u到v的长度为s的所有简单路径。

main.cpp:

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;    }    

源代码:

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");    }  

运行结果:


(5)求图中通过某顶点k的所有简单回路(若存在)

main.cpp:

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;    }    

源代码:

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");    }  

运行结果:


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

main.cpp:

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;      }  

源代码:

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的下一个邻接点              }          }      }  

运行结果:


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

main.cpp:

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;      }  

源代码:

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;      }  

运行结果:


知识点总结:

遍历思想。

学习心得:

利用遍历思想求解图问题。


0 0
原创粉丝点击