实验 6:图的实验 1 -有向图的邻接表存储实现

一、实验目的 

1 熟练理解图的相关概念;

2 掌握图的邻接矩阵的存储方法的实现;

3 学会图的遍历算法

二、实验内容 

1、自己确定一个简单无向图(顶点数、和相关结点信息)利用邻接矩阵来实现存储。实现图的构造,并完成:

1) 用深度优先和广度优秀两种算法对图进行遍历,输出顶点序列数据; 

2) 以合理的格式,输出各个顶点的邻接点; 

2、试设计一个程序,对一个有向简单图,完成上题同样的任务。 

三、设计与编码

1.本实验用到的理论知识

(1)邻接表是顺序存储结构与链式存储结构相结合的存储方法,类似于树的孩子链表表示法;

(2)在邻接表中涉及入度与出度,邻接与(到)的概念;

(3)需要用结构体定义顶点表结点和边表结点。

2.算法与设计

(1)定义一个ALGraph类

class ALGraph
{
public:
ALGraph(char a[],int n,int e);  //构造函数
~ALGraph();         //析构函数
void DFSTraverse(int v);   //深度优先遍历图
void BFSTraverse(int v);          //广度优先遍历
void Print(char a [],int length);
private:
VertexNode adjlist[MaxSize];     //存放顶点表的数组
int vertexNum,arcNum;                //图的顶点数和边数

};

3.代码

#include<iostream.h>
const int MaxSize=10;   //图最大的顶点数
int visited[MaxSize]={0};     //标志数组的visited[]为全局变量
struct ArcNode      //定义边表结点
{
int adjvex;        //邻接点域
ArcNode *next;
};
struct VertexNode           //定义顶点表结点
{
char vertex;
ArcNode *firstedge;
};
class ALGraph
{
public:
ALGraph(char a[],int n,int e);  //构造函数
~ALGraph();         //析构函数
void DFSTraverse(int v);   //深度优先遍历图
void BFSTraverse(int v);          //广度优先遍历
void Print(char a [],int length);
private:
VertexNode adjlist[MaxSize];     //存放顶点表的数组
int vertexNum,arcNum;                //图的顶点数和边数


};
ALGraph::ALGraph(char a[],int n,int e)
{
ArcNode *s;
int i,j,k;
vertexNum=n;
arcNum=e;
for(i=0;i<vertexNum;i++)        //存储顶点信息,初始化顶点表
{
adjlist[i].vertex=a[i];
adjlist[i].firstedge=NULL;
}
for(k=0;k<arcNum;k++)      //依次输入每一条边
{
cout<<"请输入边的两个顶点的序号:"<<endl;
cin>>i>>j;           //输入边所依据的两个顶点的编号
s=new ArcNode;             //生成一个边表结点s
s->adjvex=j;
s->next=adjlist[i].firstedge;       //将结点s插入到第i个边表的表头
adjlist[i].firstedge=s;
}
}
ALGraph::~ALGraph()
{
ArcNode *p=NULL;
for(int i=0;i<vertexNum;i++)
{
p=adjlist[i].firstedge;
while(p!=NULL)          //删除第i条边
{
adjlist[i].firstedge=p->next;
delete p;       //释放结点空间
p=adjlist[i].firstedge;
}
}
}
void ALGraph::DFSTraverse(int v)      //深度优先遍历图
{
ArcNode *p=NULL;
int j;
cout<<adjlist[v].vertex;
visited[v]=1;
p=adjlist[v].firstedge;       //工作指针p指向顶点v的边表
while(p!=NULL)           //依次搜索顶点v的邻接点j
{
j=p->adjvex;
if(visited[j]==0) DFSTraverse(j);
p=p->next;
}
}
void ALGraph::BFSTraverse(int v) //广度优先遍历

int Q[MaxSize];      //假设队列采用顺序存储
int front=-1,rear=-1;          //初始化队列
ArcNode *p=NULL;
cout<<adjlist[v].vertex;
visited[v]=1;           
Q[++rear]=v;    //被访问顶点入队
while(front!=rear)           //当队列非空时
{
v=Q[++front];
p=adjlist[v].firstedge;     //工作指针p指向顶点v的边表
while(p!=NULL)
{
int j=p->adjvex;           //j是顶点v的邻接点
if(visited[j]==0)
{
cout<<adjlist[j].vertex;
visited[j]=1;
Q[++rear]=j;
}
p=p->next;
}
}
}
void ALGraph::Print(char a[],int length)        //输出邻接点信息
{
for(int i=0;i<length;i++)
{
cout<<a[i]<<"->";
if(adjlist[i].firstedge!=NULL)      //当顶点a[i]的指针域firstedge非空时,说明a[i]有邻接点
cout<<a[adjlist[i].firstedge->adjvex];          //输出a[i]的邻接点
else break;
cout<<endl;
}
}
int main()
{
char ch[]={'A','B','C','D','E'};          //char型的顶点信息
ALGraph ALG(ch,5,7);     //调用构造函数      
for(int i=0;i<MaxSize;i++)           //初始化图中所有顶点均未被访问
visited[i]=0;
cout<<"深度优先遍历序列是:";
ALG.DFSTraverse(0);       //从顶点0出发进行深度优先遍历
cout<<endl;
for(i=0;i<MaxSize;i++)    //初始化图中所有顶点均未被访问
visited[i]=0;
cout<<"广度优先遍历序列是:";
ALG.BFSTraverse(0);        //从顶点0出发进行广度优先遍历
cout<<endl;
cout<<"各顶点之间的邻接关系:"<<endl;
ALG.Print(ch,5);            //输出邻接点信息
cout<<endl;
return 0;

}

四、运行结果


五、总结与心得

有一个疑问:为什么要用结构体来定义边表结点和顶点表结点而不直接在类内定义?

猜你喜欢

转载自blog.csdn.net/weixin_40803490/article/details/80524744