实习四 图及其应用 (题目: 图遍历的演示 )

一、需求分析

1.问题描述:

   很多涉及图上操作的算法都是以图的遍历操作为基础的。试写一个程序,演示连通的无向图上行遍全部结点的操作。

2.基本要求:

    以邻接多重表为存储结构,实现连通无向图的深度优先和广度优先遍历。以用户指定的结点为起点,分别输出每种遍历下的结点访问序列

和相应生成树的边集。

    3.测试数据:

                                                                   实习四 图及其应用     

题目: 图遍历的演示                             实习时间:2012/11/20

一、需求分析

1.问题描述:

   很多涉及图上操作的算法都是以图的遍历操作为基础的。试写一个程序,演示连通的无向图上行遍全部结点的操作。

2.基本要求:

    以邻接多重表为存储结构,实现连通无向图的深度优先和广度优先遍历。以用户指定的结点为起点,分别输出每种遍历下的结点访问序列

和相应生成树的边集。

    3.测试数据:

                        

二、设计

      1. 设计思想

        (1)存储结构

             邻接多重表为存储结构

        (2)主要算法基本思想

        所有代码思想均由老师授课所得:

         深度优先搜索(Depth-first Search,DFS)

        ① 首先访问起始顶点v,再访问图中与v相邻接的且未被

             访问过的任一顶点w1;

        ② 再从w1出发,访问与w1相邻接的且未被访问过的任一

             顶点w2;

        ③ 从w2出发,重复与步骤②类似的访问,直至遇到一个

             所有邻接点均被访问过的顶点为止;

        ④ 沿刚才访问的次序,反向回到一个尚有邻接点未被访

             问过的顶点,再从该顶点出发,重复与步骤③相类似

             的访问,直到所有的被访问过的顶点的邻接顶点均被

             访问过为止。

广度优先搜索(Breadth-first Search,BFS)

        ① 访问起始顶点v后,依次访问与v相邻接的所有顶点

              w1, w2, …, wt;

        ② 再按w1, w2, …, wt的顺序,访问其中每一个顶点的

             所有未被访问过的邻接顶点;对w1为:w11, w12, …,

              w1m;…;对wt为:wt1, wt2, …, wtn等;

        ③ 再按w11, w12, …, w1m, w21, …, wt1, wt2, …, wtn的顺序,

             去访问它们各自的未被访问过的邻接顶点。依次类

             推,直到图中所有被访问过的顶点的邻接顶点都被

             访问过为止。

    2. 设计表示

        (1)函数调用关系图

          main→Initilized→CreateGraph→SetMark→DFS→BFS

     (2)函数接口规格说明    

void Initilized(Graph *graph)       // graph指向的图的初始化

void CreateGraph(Graph *graph)    //graph指向的图的创建图

void SetMark(Graph *graph)       //设置graph指向的图的顶点访问标记

void DFS(Graph *graph,int v)       //深度遍历graph指向的图的点amlist [v]

void BFS(Graph *graph,int u)       //广度遍历graph指向的图的点amlist [v]

3. 实现注释    (即各项功能的实现程度)

程序缺乏健壮性。     

4. 详细设计(主要函数)  

【1】void Initilized(Graph *graph)//图的初始化

{

 graph=(Graph  *)malloc (sizeof(Graph));

 graph->numberOfVerts =0;

 graph->numberOfEerts =0;

}

【2】void CreateGraph(Graph *graph)//图的创建图

{

 ENode *p,*q,*e;

 int i;

 printf("请输入连通无向图的顶点数和边数 例如 3 3:\n");

 scanf("%d %d",&graph->numberOfVerts,&graph->numberOfEerts);

 for(i=1;i<=graph->numberOfVerts;i++)

 {

  printf("请输入第%d个顶点的信息:\n",i);

  scanf("%s",&graph->amlist [i].data );

   graph->amlist [i].number  =i;

  graph->amlist[i].firstedge=NULL;

   graph->amlist [i].mark =0;

 }

 for(i=1;i<=graph->numberOfEerts;i++)

 {

  p=(ENode *)malloc(sizeof(ENode));

  printf("请输入每条边的信息(编号小的在前 例如1 3回车1 2回车2 3)\n");

  scanf("%d %d",&p->ivex,&p->jvex);

  p->ilink =p->jlink =NULL;

  if(graph->amlist [p->ivex ].firstedge==NULL )

   graph->amlist [p->ivex ].firstedge =p;

  else

  {

   q=graph->amlist [p->ivex ].firstedge ;

   while(q!=NULL)

   {

    e=q;

    if(q->ivex ==p->ivex )

     q=q->ilink ;

    else

     q=q->jlink ;

   }

   if(e->ivex ==p->ivex )

    e->ilink =p;

   else

    e->jlink =p;

  }

  if(graph->amlist [p->jvex ].firstedge==NULL )

   graph->amlist [p->jvex ].firstedge =p;

  else

  {

   q=graph->amlist [p->jvex ].firstedge ;

   while(q!=NULL)

   {

    e=q;

    if(q->ivex ==p->ivex )

     q=q->ilink ;

    else

     q=q->jlink ;

   }

   if(e->ivex ==p->ivex )

    e->ilink =p;

   else

    e->jlink =p;

  }

 }

}

【3】void SetMark(Graph *graph)//设置访问标记

{

 int i;

 for(i=1;i<=graph->numberOfVerts ;i++)

  graph->amlist [i].mark =0;

}

【4】void DFS(Graph *graph,int v)//深度遍历

{

 ENode *p;

 printf("%d            ",v);

 graph->amlist [v].mark =1;

 p=graph->amlist [v].firstedge ;

 while(p!=NULL)

 {

  if(p->ivex ==v)

  {

   if(graph->amlist [p->jvex ].mark ==0)

   {

    printf("<%d,%d>\n",p->ivex ,p->jvex );

    DFS(graph,p->jvex );

   }

   p=p->ilink ;

  }

  else

  {

   if(graph->amlist [p->ivex].mark ==0)

   {

    printf("<%d,%d>\n",p->jvex ,p->ivex );

    DFS(graph,p->ivex );

   }

   p=p->jlink ;

  }

 }

}

【5】void BFS(Graph *graph,int u)//广度遍历

{

 LinkQueue Q;

 ENode *p;

 InitQueue(&Q);

 printf("%d            ",u);

 graph->amlist [u].mark =1;

 QueueAppend(&Q,u);

 while(Q.front !=Q.rear )

 {

  QueueDelete(&Q,&u);

  p=graph->amlist [u].firstedge ;

  while(p!=NULL)

  {

   if(p->ivex ==u)

   {

    if(graph->amlist [p->jvex ].mark ==0)

    {

     QueueAppend(&Q,p->jvex );

     graph->amlist [p->jvex ].mark =1;

     printf("<%d,%d>\n",p->ivex ,p->jvex );

     printf("%d            ",p->jvex );

    }

    p=p->ilink ;

   }

   else

   {

     if(graph->amlist [p->ivex ].mark ==0)

     {

      QueueAppend(&Q,p->ivex );

      graph->amlist [p->ivex ].mark =1;

      printf("<%d,%d>\n",p->jvex ,p->ivex );

      printf("%d            ",p->ivex );

     }

     p=p->jlink ;

   }

  }

 }

}

三、调试分析

      1.调试过程中遇到的主要问题是如何解决的;

调试过程中存在少许C语言的基础语法错误,经独立仔细观察和调试修改正确,最大的难题是将图中的各类算法实践要运用上几章节的内容,实现时需不断的温习以前的知识,出现多次错误。终于在自己独立多次多天修改下,终于完成。     

2.对设计和编码的回顾讨论和分析;

总的来说,这个程序写的相当困难,虽然老师已经把大体算法思路都提到过。但是,由于算法和语法的知识掌握的太不牢固,对好多以前学的数据结构还不是特别熟悉,需要不断尝试与温习。所以,今后应该多温习多练习才好。

3.时间和空间复杂度的分析;

【1】:广度遍历算法 时间O(n),空间O(1)

       【2】:深度遍历算法 时间O(n),  空间O(1)

      4.改进设想;

       程序能实现预期功能,只是其中的改进空间可能较大

【1】:图的构造函数

       【2】:广度遍历算法

5.经验和体会等。

多动手编程,才能熟练灵活的掌握C语言基础知识,才能更好的理解掌握数据结构的精髓。从而避免基础语法错误,让代码变得更简洁高效。如此才能准确高效的解决问题。在今后的编程过程中要更注重代码的熟练掌握,多的温习代码思想,多的动手编程。

四、用户手册(即使用说明)

   仅需按照提示的例子输入即可。若出错,则重新来过。

五、运行结果

运行环境:C-free

测试数据:

六、源程序清单

https://wenku.baidu.com/view/7b6254df640e52ea551810a6f524ccbff121cab5

原文地址:https://www.cnblogs.com/XDJjy/p/3006000.html