第七天--------图的基本操作(实验报告)附源码

一、 实验目的

1.掌握图的存储思想及其存储实现。

    2.掌握图的深度、广度优先遍历算法思想及其程序实现。

二、实验内容

1、实验内容

a)      键盘输入数据,分别建立一个有向图和一个无向图的邻接表。

b)      输出该邻接表。

c)      在有向图的邻接表的基础上计算各顶点的度,并输出。

d)      采用邻接表存储实现无向图的深度优先遍历。

扫描二维码关注公众号,回复: 2400920 查看本文章

e)      采用邻接表存储实现无向图的广度优先遍历。

f)       在主函数中设计一个简单的菜单,分别调试上述算法。

g)      *综合训练

地下迷宫探索:假设有一个地下通道迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关。请问你如何从某个起点开始在迷宫中点亮所有的灯并回到起点?

输入格式:

输入第一行给出三个正整数,分别表示地下迷宫的节点数N(1<N≤1000,表示通道所有交叉点和端点)、边数M(M≤3000,表示通道数)和探索起始节点编号S(节点从1到N编号)。随后的M行对应M条边(通道),每行给出一对正整数,分别是该条边直接连通的两个节点的编号。

输出格式:

若可以点亮所有节点的灯,则输出从S开始并以S结束的包含所有节点的序列,序列中相邻的节点一定有边(通道);否则虽然不能点亮所有节点的灯,但还是输出点亮部分灯的节点序列,最后输出0,此时表示迷宫不是连通图。

由于深度优先遍历的节点序列是不唯一的,为了使得输出具有唯一的结果,我们约定以节点小编号优先的次序访问(点灯)。在点亮所有可以点亮的灯后,以原路返回的方式回到起点。

输入样例:

6 8 1

1 2

2 3

3 4

4 5

5 6

6 4

3 6

1 5

输出样例:

1 2 3 4 5 6 5 4 3 2 1

2、主要数据类型与变量

a)      1.类型定义(邻接表存储)

b)              #define MAX_VERTEX_NUM 20  //顶点最大个数

c)              typedef struct ArcNode{

d)                 int            adjvex;

e)                 struct ArcNode *nextarc;

f)                  int            weight;  //边的权值

g)              }ArcNode;  //表结点

g)        #define VertexType int  //顶点元素类型

h)              typedef struct VNode{ 

i)                   VertexType data;

j)                   ArcNode *firstarc;

k)              }VNode,AdjList[MAX_VERTEX_NUM]; //

l)                typedefstruct{

m)      AdjListvertices;

n)                int vexnum, arcnum; //顶点的实际数,边的实际数

o)                int kind;

p)             }ALGraph; 

q)      2.上述类型定义可以根据实际情况适当调整。

r)       3.算法4、5分别利用栈、队列实现非递归算法。

3、算法思想描述

三、系统测试

1、测试方案

通过输入图的定点数和边数,来确定出整个图的大致变化,当然是自己现在草稿纸上画出这个图,然后写出答案。在执行程序,看看程序的答案与自己的答案是否相同。


附:程序源代码

ALGraph.cpp

#include "ALGraph.h"

int visited[N];

/*创建一个无向图的邻接表*/

int CreateUDG(ALGraph &G)

{

   int m, n, k;

   char v1, v2;

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

   scanf("%d %d", &G.vexnum, &G.arcnum);

   printf("请输入%d个顶点名字(以空格区分):", G.vexnum);

    for(m = 0; m < G.vexnum; m++)

    {

       scanf(" %c", &G.vertices[m].data);  /*请注意输入格式*/

       G.vertices[m].firstarc = NULL; /*邻接表初始化为空*/

    }

   for(k = 1; k <= G.arcnum; k++)

    {

       printf("请输入第%d条边的两个顶点(以字符表示,字符间以空格区分):", k);

       scanf(" %c %c", &v1, &v2);  /*请注意输入格式*/

       m = LocateVex(G, v1);     

       n = LocateVex(G, v2);

       InsertList(G, m, n,0);   /*生成各自的邻接表*/

       InsertList(G, n, m,0);

    }

   return OK;

}

/*请写出有向图的邻接表的生成函数*/

int CreateDG(ALGraph &G)

{

   int m, n, k;

   char v1, v2;

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

   scanf("%d %d", &G.vexnum, &G.arcnum);

   printf("请输入%d个顶点名字(以空格区分):", G.vexnum);

   for(m = 0; m < G.vexnum; m++)

    {

       scanf(" %c", &G.vertices[m].data);  /*请注意输入格式*/

       G.vertices[m].firstarc = NULL; /*邻接表初始化为空*/

    }

   for(k = 1; k <= G.arcnum; k++)

    {

       printf("请输入第%d条边的两个顶点(以字符表示,字符间以空格区分,第一个为尾,第二个为头):", k);

       scanf(" %c %c", &v1, &v2);  /*请注意输入格式*/

       m = LocateVex(G, v1);       /*确定v1和v2的下标*/

        n = LocateVex(G, v2);

       InsertList(G, m, n,0);   /*生成各自的邻接表*/

    }

   return OK;

}

/*请写出无向带权图的邻接表的生成函数*/

int CreateUDN(ALGraph &G)

{

   int m, n, k,w;

   char v1, v2;

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

   scanf("%d %d", &G.vexnum, &G.arcnum);

   printf("请输入%d个顶点名字(以空格区分):", G.vexnum);

   for(m = 0; m < G.vexnum; m++)

    {

       scanf(" %c", &G.vertices[m].data);  /*请注意输入格式*/

       G.vertices[m].firstarc = NULL; /*邻接表初始化为空*/

    }

   for(k = 1; k <= G.arcnum; k++)

    {

       printf("请输入第%d条边的两个顶点和权值(以字符表示,字符间以空格区分):", k);

       scanf(" %c %c %d", &v1, &v2, &w);  /*请注意输入格式*/

       m = LocateVex(G, v1);       /*确定v1和v2的下标*/

       n = LocateVex(G, v2);

       InsertList(G, m, n,w);   /*生成各自的邻接表*/

       InsertList(G, n, m,w);

    }

   return OK;

}

/*请写出有向带权图的邻接表的生成函数*/

int CreateDN(ALGraph &G)

{

 intm, n, k,w;

   char v1, v2;

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

   scanf("%d %d", &G.vexnum, &G.arcnum);

   printf("请输入%d个顶点名字(以空格区分):", G.vexnum);

   for(m = 0; m < G.vexnum; m++)

    {

       scanf(" %c", &G.vertices[m].data);  /*请注意输入格式*/

       G.vertices[m].firstarc = NULL; /*邻接表初始化为空*/

    }

   for(k = 1; k <= G.arcnum; k++)

    {

       printf("请输入第%d条边的两个顶点和权值(以字符表示,字符间以空格区分,第一个为尾,第二个为头):", k);

       scanf(" %c %c %d", &v1, &v2, &w);  /*请注意输入格式*/

       m = LocateVex(G, v1);       /*确定v1和v2的下标*/

       n = LocateVex(G, v2);

       InsertList(G, m, n, w);   /*生成各自的邻接表*/

    }

   return OK;

}

/*查找顶点v在邻接表存储法中的下标*/

int LocateVex(ALGraph G, char v)

{

   int m;

   for(m = 0; m < G.vexnum; m++)

       if(G.vertices[m].data == v)

           return m;

   return ERROR;

}

/*在邻接表中插入顶点v的邻接点w*/

int InsertList(ALGraph &G, int m, intn,int w)

{    // 给新加入的节点分配内存;

    ArcNode *p;

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

    p->adjvex = n;

    p->weight = w;

    p->nextarc = G.vertices[m].firstarc;

    G.vertices[m].firstarc = p;

    return OK;

}

/*遍历顶点v的邻接表*/

void TraverseList(ALGraph G, int v)

{

   ArcNode *p;

   int m;

    p= G.vertices[v].firstarc;

   while(p)

    {

       m = p->adjvex;

       printf("%c ", G.vertices[m].data);

       p = p->nextarc;

    }

}

/*计算顶点v的邻接表长度*/

int LengthList(ALGraph G, int v)

{

  ArcNode *p;

  int m = 0;

  if(G.vertices[v].firstarc == NULL){

    return 0;

   }

   p= G.vertices[v].firstarc; m++;

  while(p->nextarc != NULL){

    m++;

    p = p->nextarc;

   }

  return m;

}

/*深度优先遍历*/

void DFSTraverse(ALGraph G)

{

   int m;

   for(m = 0; m < G.vexnum; m++)

       visited[m] = FALSE;

   for(m = 0; m < G.vexnum; m++)

       if(!visited[m])  DFS(G, m);

   printf("\n");

}

void DFS(ALGraph G, int v)

{

   int w;

   visited[v] = TRUE; /*访问顶点v, 并置访问标志数组相应分量值*/

   printf("%c ", G.vertices[v].data);

   for(w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w))

       if(!visited[w])  DFS(G, w);   /*递归调用DFS*/

} /*DFS*/

/*在图G中查找顶点v的第一个邻接点*/

int FirstAdjVex(ALGraph G, int v)

{

   if(G.vertices[v].firstarc)

       return G.vertices[v].firstarc->adjvex;  /*邻接表的第一个结点信息*/

   else

        return ERROR;

}

/*在图G中查找顶点v的邻接点w之后的下一个邻接点*/

int NextAdjVex(ALGraph G, int v, int w)

{

    ArcNode *p;

    int m;

    p = G.vertices[v].firstarc;

    while(p){

       if(p->nextarc == NULL) return ERROR;

       m = p->adjvex;

       if(m == w){

          w = p->nextarc->adjvex;

          break;

       }

       p = p->nextarc;

    }

    return w;

}

void BFSTraverse(ALGraph G)

{

   int m;

   for(m = 0; m < G.vexnum; m++)

       visited[m] = FALSE;

   for(m = 0; m < G.vexnum; m++)

       if(!visited[m])  BFS(G, m);

   printf("\n");

} //BFSTraverse

void BFS(ALGraph G, int v){

   QElemType e;

   ArcNode *p;

   LinkQueue q;

   InitQueue(q);

   EnQueue(q,v);

   visited[v] = TRUE;

   while(!QueueEmpty(q)){

    DeQueue(q,e); printf("%c ",G.vertices[e].data);

    p = G.vertices[e].firstarc;

    while(p){

      if(!visited[p->adjvex]){

       EnQueue(q,p->adjvex); visited[p->adjvex] = TRUE;

      }

      p = p->nextarc;

    }

  }

}

/*计算有向图中各顶点的度*/

void CountNum(ALGraph G, int *ID)

{

  ArcNode *p;

  int r[G.vexnum],c[G.vexnum];//c为出度,r为入度。

  for(int m=0;m<G.vexnum;m++){

      c[m] = LengthList(G,m);

   }

  for(int m=0;m<G.vexnum;m++){

      r[m] = 0;

   }

  for(int m=0;m<G.vexnum;m++){

    p = G.vertices[m].firstarc;

    while(p){

       r[p->adjvex]++;

       p = p->nextarc;

    }

   }

  for(int m=0;m<G.vexnum;m++){

   ID[m] = c[m]+r[m];

   }

}

ALGraph.h

#include "DS.h"

#include "LinkQueue.h"

#ifndef ALGRAPH_H_INCLUDED

#define ALGRAPH_H_INCLUDED

#define N  10

typedef char  VertexType;

typedef struct ArcNode 

{

   int   adjvex;

   int weight;

   struct ArcNode  *nextarc;

}ArcNode;

typedef struct  VNode

{

   VertexType   data;

   ArcNode     *firstarc; 

}VNode,AdjList[N];

typedef struct

{

   AdjList   vertices;

    int      vexnum, arcnum;    

}ALGraph;

#endif // ALGRAPH_H_INCLUDED

int CreateUDG(ALGraph &G);

int CreateDG(ALGraph &G);

int CreateUDN(ALGraph &G);

int CreateDN(ALGraph &G);

int LocateVex(ALGraph G, char v);

int InsertList(ALGraph &G, int i, intj,int w);

void TraverseList(ALGraph G, int v);

int LengthList(ALGraph G, int v);

int FirstAdjVex(ALGraph G, int v);

int NextAdjVex(ALGraph G, int v, int w);

void DFSTraverse(ALGraph G);   

void DFS(ALGraph G, int v);

void BFSTraverse(ALGraph G);    

void BFS(ALGraph G, int v);

void CountNum(ALGraph G, int *ID);

main.cpp

#include "ALGraph.h"

int main()

{

   ALGraph G;

   int i;

   //创建无向图

   CreateUDG(G);

   int Num[G.vexnum];

   printf("无向图的邻接表为:\n");

   for(i = 0; i < G.vexnum; i++)

    {

       printf("%c  ——>  ", G.vertices[i].data);

       TraverseList(G, i);

       printf("\n");

    }

   printf("DFS序列:");

   DFS(G,0);

   printf("\n");

   DFSTraverse(G);

   printf("BFS序列:");

   BFSTraverse(G);

   printf("图中各顶点的度为:\n");

   CountNum(G, Num);

   for(i = 0;i<G.vexnum;i++){

       printf("图中%d点的度为:%d\n",i+1,Num[i]);

    }

   return 0;

}


         
         
       
       
     
 

猜你喜欢

转载自blog.csdn.net/iiiiiilikangshuai/article/details/80918742
今日推荐