实验目的

图基本操作的编程实现

要求:

图基本操作的编程实现(2学时,验证型),掌握图的建立、遍历、插入、删除等基本操作的编程实现,存储结构可以在顺序结构、链接结构、联合使用多种结构等中任选,也可以全部实现。也鼓励学生利用基本操作进行一些应用的程序设计。

实验性质

验证性实验(学时数:2H)

实验内容

编程对图进行存储(邻接矩阵或邻接表都可以,由学生自由选择),之后可以询问任何两个结点之间是否有通路和路径数。

设计一个将图形转成邻接链表的程序。

设计一个深度优先搜索法来查找图形的程序。

设计一个广度优先搜索法来查找一个图形的程序。

鼓励开发出难度更高的程序。

注意事项

1.开发语言:使用C。

2.可以自己增加其他功能。

实验分析、说明过程                                                  

【深度遍历】

深度遍历程序主要是利用了栈的先进后出的思想,回溯,递归的思想,而广度遍历主要是利用了队列的思想,先进先出。

1先从开始指定的结点进行访问,然后标记位它为一,(代表他已经被访问过)

2然后取他的第一个邻接点。

3然后进入循环,循环条件为邻接点不为空,如果这个邻接结点,没有被标记,则执行语句递归,再次执行该函数,然后再继续寻找该点的邻接结点,依次进行下去,最后直到递归返回到第一层,结束程序。

【广度遍历】

1.从某个结点开始,把这个结点入队,然后设置标志为1.

2.执行循环体里面的内容,条件为队列不为空,循环体,先将队列出队,然后查找这个点是否具有邻接点,如果有结点先判断这个邻接点是否时被标记过的,如果没被标记,就先访问这个结点,设置标志位为1,然后入队。

3.反复进行2步骤,直到队列为空。

思考问题

  1. 图的定义和特性?

 定义和特性图 (Graph) 是由若干给定的顶点及连接两顶点的边所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系。顶点用于代表事物,连接两顶点的边则用于表示两个事物间具有这种关系。
图论 (Graph theory) 是数学的一个分支,图是图论的主要研究对象。
表达式:G=(V, E)
V:顶点(数据元素)的有穷非空集合。
E:边的有穷集合。
Graph = (Vertex, Edge)

  1. 图的主要存储结构是什么?是独立的某种还是多种数据结构的综合?

答:存储结构主要是邻接矩阵和邻接表。不是独立的。

  1. 图的主要遍历思路是哪些?

广度优先搜索思想:从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到。如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。

深度优先搜索思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到。若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

  1. 举出图的应用范例?

答:道路畅通工程和最短路径

实验小结 (总结本次实验的重难点及心得、体会、收获)

对于这次的实验,由于图的思想还是不能很好的理解,在图的遍历的时候,主要有利用邻接矩阵为存储结构,但是对于它的遍历的思路还不是十分的清晰,有时还会混淆,在自己做完实验以后,又继续对代码进行研究,还有遍历的思路进行整理,一遍一遍的画图,对照着程序画图,将它遍历的思想深深地理解,现可以利用图进行编写程序,也有了那些思想,现在编写那些程序觉得比以前好了不少,最起码思路有了一个很大的跃升,编写代码顺着思路及可以了,虽然还是有不少的漏洞。

附录-实验代码

#include<stdio.h>

#include<conio.h>

#include <stdlib.h>

#define vertexnum 100       //定义最大可输入的结点个数

typedef struct  node        //定义图形的顶点结构

{

   int  vertex;             //图中的顶点信息为数字

   struct  node  *next;

}Graph;

Graph head[vertexnum];      //邻接表的表头结点

int Visited[vertexnum];     //遍历记录

void Create_l_Graph(int Vertex1,int Vertex2,int no)

{                      //以邻接链表建立图形

  Graph  *searchP;     //结点声明

  Graph  *New;         //新结点声明

  New=(Graph *)malloc(sizeof(struct node));

  if (New!= NULL )

  {

    New->vertex=Vertex2;

    New->next=NULL;

    searchP=&(head[Vertex1]);

    while(searchP->next!=NULL)

       searchP=searchP->next;

    searchP->next =New;

if(no==0)

{

New=(Graph *)malloc(sizeof(struct node));

New->vertex=Vertex1;

        New->next=NULL;

        searchP=&(head[Vertex2]);

        while(searchP->next!=NULL)

           searchP=searchP->next;

        searchP->next =New;

    }

  }

}

void showmenu()

{                   //显示菜单

printf("    欢迎使用图的操作演示软件\n");

printf("\t1、创建图的邻接表\n");

printf("\t2、图的输出\n");

printf("\t3、图的深度优先遍历\n");

printf("\t4、退出程序\n");

}

void print_l_graph(Graph *head)

{                     //输出邻接链表的数据

    Graph  *searchP;

    searchP=head->next;

    while(searchP!=NULL)

    {

           printf("%d",searchP->vertex);                           

           searchP=searchP->next;                           

     }

    printf("\n");

}

void DFS(int vertex)

{                                       //深度优先遍历

    Graph *SearchP;                      //结点声明

                                         //标记某个结点已遍历过

    printf("[%d]==>",vertex);

    SearchP=head[vertex].next;

    while(SearchP!=NULL)

    {

        if(!Visited[SearchP->vertex])       //判断结点未被遍历过

            DFS(SearchP->vertex);                             //递归调用深度优先遍历函数

        SearchP=SearchP->next;                 //下一个邻接点

    }

}

void main()

{

   int source;           //图中一条边的起始顶点

   int destination;      //图中一条边的终止顶点

   int i,j;

   int vermax;           //定义图中最大的顶点数

   int edgemax;          //定义图中最大的边数

   int choice;

   int no;

   while(1)

{

showmenu();

printf("   请输入你的选择:");

scanf("%d",&choice);

fflush(stdin);//清除键盘缓冲区

switch(choice)

{

          case 1:printf("请输入图的类别(有向图-1,无向图-0):");

     scanf("%d",&no);

     printf("请输入图中的总顶点数和边数:");

                 scanf("%d%d",&vermax,&edgemax);

     for(i=1;i<vermax;i++)

{

head[i].vertex = i;

head[i].next = NULL;

}

for(i=1;i<=edgemax;i++)

{

printf("请输入第%d条边的起点:",i);

scanf("%d",&source);

printf("请输入第%d条边的终点:",i);

scanf("%d",&destination);

if(source==destination)    

   printf("输入有误!\n");//出错:自身循环

        else                      //调用建立邻接链表

                        Create_l_Graph(source,destination,no);

}

     printf("图创建成功,按任意键继续…\n");

 getch();

 system("cls");

 break;

  case 2:printf("图的邻接表如下:\n");  

 for(i=1;i<=vermax;i++)

{

printf("顶点[%d]:",i);

print_l_graph(&head[i]);//调用输出邻接链表数据

}

 printf("\n");

 system("pause");

 system("cls");

 break;

  case 3:for(i=1;i<=vermax;i++)

                     Visited[i]=0;

     printf("请输入遍历的起点:");

 scanf("%d",&source);

     printf("图的深度优先遍历结果为:\n");

     DFS(source);

 printf("END\n");

 system("pause");

 system("cls");

 break;

  case 4:return;

  default:

     printf("你的输入有误,请从新输入!\n");

 system("pause");

 system("cls");

}

}

 }

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐