图的存储与遍历

一、图的主要存储方式主要有两种:

1.邻接表表示;

2.数组表示;

其中邻接表适用于稀疏图,数组表示法适用于稠密图。由邻接表表示延伸开的还有十字链表法等。本文利用邻接表表示图,实现图的存储与遍历。

二、邻接表

邻接表分为两个部分,一部分为顶点表,可用数组表示,另一部分为边表,利用链表表示。在邻接表中,对图中的每个顶点建立一个单链表,第i个单链表中的结点表示依附于vi的边。顶点结点有两部分组成:一是存储顶点vi的名或其他信息的数据域,另一个是指向链表中第一个结点的链域;边表结点的组成为三部分,一是邻接点域(adjvex)指示与顶点vi邻接的点在图中的位置,链域(nextarc)指示下一条边或弧的结点;数据域存储与边或弧有关的信息。具体结构图如下:

                                边表结点                                                                              顶点表结点

    


三、图的遍历

         1.深度优先搜索(DFS):顾名思义就是从图中某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v路径相通的顶点都被访问到;若此时尚有顶点未被访问,则另选图中一个未曾被访问的顶点做起始点,重复上述过程,直至图中所有顶点均被访问过。

          2.广度优先搜索(BFS):从图中某个顶点出发,在访问了v之后,依次访问v的各个未曾被访问过的邻接点,然后分别从这些邻接点出发依次访问它们它们的邻接点,并使“先被访问过的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。若此时尚有顶点未被访问,则另选图中一个未曾被访问的顶点做起始点,重复上述过程,直至图中所有顶点均被访问过。

#ifndef DefinitionOfGraph_H
#define  DefinitionOfGraph_H


#include  <iostream>
#include <queue>
using namespace std;

//*****************邻接表的定义******************
//************************************************
#define MAX_VERTEX_NUM 20
typedef struct ArcNode {
	int adjvex;
	struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode{
	char data;
	ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct{
	AdjList vertices;
	int vexnum,arcnum;
	int kind;
}ALGraph;


bool visited1[MAX_VERTEX_NUM ];
bool visited2[MAX_VERTEX_NUM];
//***********图的操作函数原型****************
//********************************************
void CreatGraph(ALGraph *G);//邻接表存储图
void DFS(ALGraph G,int v);
void DFSTraverse(ALGraph G);
void VisitFun(ALGraph G,int v);
void BFS(ALGraph G,int v);
void BFSTraverse(ALGraph G);

//***********图的函数操作定义****************
//********************************************
void CreatGraph(ALGraph *G)
{
	int vi,vj;
	ArcNode *s;
	cout<<"请输入图的顶点个数:";
	cin>>G->vexnum;
	cout<<endl;
	cout<<"请输入图的边的个数:";
	cin>>G->arcnum;
	cout<<endl;
	cout<<"请输入顶点信息(顶点编号):"<<endl;
	for(int i=0;i<G->vexnum;i++)
	{//建立顶点表
		cin>>G->vertices[i].data;//读入顶点信息
		G->vertices[i].firstarc=NULL;//使顶点结点的指针域指向空指针域	
	}
	cout<<"顶点表已建好!"<<endl;
	for(int k=0;k<G->arcnum;k++)
	{
		cout<<"请输入边的信息(输入格式为:<vi,vj>):"<<endl;
		cin>>vi>>vj;//vi,vj是边<vi,vj>的两个结点
		s=new ArcNode;
		s->adjvex=vj;//邻接点序号为vj;
		s->nextarc=G->vertices[vi].firstarc;//将新的边表结点s插入到顶点vi的边表头部,这是逆序建立边表结点
		G->vertices[vi].firstarc=s;
		s=new ArcNode;
		s->adjvex=vi;
		s->nextarc=G->vertices[vj].firstarc;
		G->vertices[vj].firstarc=s;
	}
}
void VisitFun(ALGraph G,int v)
{
	cout<<"本次访问的顶点为:"<<G.vertices[v].data<<endl;
}

void DFSTraverse(ALGraph G)
{
	for(int i=0;i<G.vexnum;i++)
		visited1[i]=false;
	for(int i=0;i<G.vexnum;i++)
	{
		if(!visited1[i])
			DFS(G,i);
	}
}
void DFS(ALGraph G,int v)
{	
	//从第v个顶点开始遍历
	visited1[v]=true;
	VisitFun(G,v);
	ArcNode *p;
	p=G.vertices[v].firstarc;
	while(p)
	{
		if(!visited1[p->adjvex])
			DFS(G,p->adjvex);
		p=p->nextarc;	
	}
}
void BFS(ALGraph G,int v)
{
	queue<int>Q;
	 ArcNode *p;
	cout<<"本次访问的顶点为:"<<G.vertices[v].data<<endl;
	visited2[v]=true;
	Q.push(v);
	while(!Q.empty())
	{
		int k;
		k=Q.front();
		Q.pop();
		p=G.vertices[k].firstarc;
		while(p)
		{
			if(!visited2[p->adjvex])
			{
			    cout<<"本次访问的顶点为:"<<G.vertices[p->adjvex].data<<endl;
				visited2[p->adjvex]=true;
				Q.push(p->adjvex);
		    }
			p=p->nextarc;
	    }
    }
}
void BFSTraverse(ALGraph G)
{
	for(int i=0;i<G.vexnum;i++)
		visited2[MAX_VERTEX_NUM]=false;
	for(int i=0;i<G.vexnum;i++)
	{
		if(!visited2[i])
		{
				BFS(G,i);
		}
	}
}
#endif

测试:




注意:这是逆序建立边表!

如有错误,欢迎各位大神指正!


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值