图的存储与遍历

1.图的存储结构有两种,第一种是邻接矩阵,第二种是邻接表。邻接矩阵是表示顶点之间相邻关系的矩阵。

邻接表:是图的一种链接存储结构。在邻接表中,对图的每一个顶点建立一个带头结点的单链表,所有的头节点构成一个数组,第i个单链表中的结点表示依附于顶点vi的边。单链表中每个节点由两个域组成:顶点域adjvex,用以指示该邻接点在头结点数组中的序号(下标);链域next, 用以指示依附于顶点vi的下一条边所对应的结点。如果用邻接表存放网中的信息,则需要添加一个存放权重的域value.

注意:一个图的邻接矩阵表示是唯一的,但是邻接表表示不唯一。


图的邻接矩阵与邻接表表示方法如下:

#include<iostream>
#include<queue>
using namespace std;
/*线性表的存储*/
//1.邻接表
const int MaxVex=100;//图中最大顶点个数
typedef char VertexType;

/*定义图的顶点信息*/
typedef struct vertex
{
	int adjvex;//顶点编号
	VertexType data;//顶点信息

}VType; //表示顶点的类型

/*定义一个图的邻接矩阵的类型,包含所有的顶点和边*/
typedef struct graph
{
	int n; //图的实际顶点数
	int e;//图的实际边数
	VType ves[MaxVex];//顶点集合
	int edges[MaxVex][MaxVex];//边的集合

}AdjMatix;

/*创建一个带权有向图的邻接矩阵表示*/

int CreateMatix(AdjMatix &g)
{
int i,j,k,w;
VertexType b,t;
cout<<"输入顶点数(n)和边数(e):";
cin>>g.n>>g.e;

/*输入节点信息*/
for(i=0;i<g.n;i++)
{
	cout<<" 序号为"<<i<<"的顶点信息:";
	cin>>g.ves[i].data;
	g.ves[i].adjvex=i;
}
/*边初始化*/
for(i=0;i<g.n;i++)
for(j=0;j<g.n;j++)
{
	g.edges[i][j]=0;
}
/*创建边*/
for(k=0;k<g.e ;k++)
{
	cout<<" 序号为"<<k<<"的变=》";
	cout<<" 起点  终点 权值:";
	cin>>b>>t>>w;
	i=0;
	while(i<g.n&&g.ves[i].data!=b)
		i++;
	if(i>=g.n)
	{
		cout<<"输入的起点不存在"<<endl;
		return 0;
	}
	j=0;
	while(j<g.n&&g.ves[j].data!=t)
		j++;
	if(j>=g.n)
	{
		cout<<"输入的终点不存在"<<endl;
		return 0;
	}
	g.edges[i][j]=w;

}
return 1;

}
/*显示图的邻接矩阵*/
void DispMatix(AdjMatix g)
{
	int i,j;
	cout<<"\n图的邻接矩阵:\n";
		for(i=0;i<g.n;i++)
		{
			for(j=0;j<g.n ;j++)
				cout<<"  "<<g.edges[i][j];
			cout<<endl;
		}
}


/*图的邻接表表示*/
typedef struct edgenode
{
	int adjvex; //邻接点序号
	int value; //边的权值
	struct edgenode *next;//下一条边的顶点
}ArcNode;   //每个顶点建立的单链表中节点的类型

typedef struct vexnode
{
	VertexType data; //节点信息
	ArcNode *fristarc;//指向第一条边节点

}VHeadNode; //单链表头节点类型

//图的邻接表类型
typedef struct
{
	int n,e;
	VHeadNode adjlist[MaxVex];//单链表头节点数组
}AdjList;

/*创建一个无向图的邻接表表示*/
int CreateAdjList(AdjList *&g)
{
	int i,b,t,w;
	ArcNode *p,*q;
    g=(AdjList *)malloc(sizeof(AdjList));
cout<<"输入顶点数(n)和边数(e):";
cin>>g->n>>g->e;

/*输入节点信息*/
for(i=0;i<g->n;i++)
{
	cout<<" 序号为"<<i<<"的顶点信息:";
	cin>>g->adjlist[i].data;
	g->adjlist[i].fristarc=NULL;
}

for(i=0;i<g->e;i++)
{
   cout<<" 序号为"<<i<<"的边=》";
	cout<<" 起点  终点 权值:";
	cin>>b>>t>>w;
	if(b<0||b>g->n)
	{
		cout<<"输入的起点序号不存在"<<endl;
		return 0;
	}
 if(t<0||t>g->n)
	{
		cout<<"输入的终点序号不存在"<<endl;
		return 0;
	}


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

 p->value=w;
 p->adjvex=t;

 p->next=g->adjlist[b].fristarc;//将p插入到adjlist[b]的单链表之首

 g->adjlist[b].fristarc=p;

q=(ArcNode *)malloc(sizeof(ArcNode));
q->value=w;
q->adjvex=b;
q->next=g->adjlist[t].fristarc;
g->adjlist[t].fristarc=q;
}


return 1;
}

 
/*显示图的连接表*/

void DispAdjList(AdjList *g)
{
	int i;
	ArcNode *p;
	cout<<"图的邻接表表示如下:"<<endl;
	for(i=0;i<g->n;i++)
	{
		cout<<" ["<<i<<","<<g->adjlist[i].data<<"]=>";
		p=g->adjlist[i].fristarc;

		 while(p!=NULL)
		 {
			 cout<<"("<<p->adjvex<<","<<p->value<<")->";
			 p=p->next;
		 }
		 cout<<"^\n";
	}
}

/*图的搜索*/

// 广度优先搜索
void BFS(AdjList *g,int vi) //对邻接表g从顶点vi开始进行广度优先遍历
{

	int i,v,visited[MaxVex];
	queue<int> qu;  //队列,保存节点

	ArcNode *p;
	for(i=0;i<g->n;i++)
		visited[i]=0;
	visited[vi]=1;
	cout<<vi<<" ";
	qu.push(vi);
	while(!qu.empty())  //当队列不为空时循环
	{
		v=qu.front();  //出队列
		qu.pop();
		p=g->adjlist[v].fristarc;//查找v的第一个邻接点

		while(p!=NULL)
		{
			if(visited[p->adjvex]==0)
			{
				visited[p->adjvex]=1;
				cout<<p->adjvex<<" ";//访问该节点并入队列

				qu.push(p->adjvex);
			}
			p=p->next;
		}
 
	}


}

//深度优先搜索的递归算法
int vis[MaxVex];
void DFS(AdjList *g,int vi)
{
	ArcNode *p;
	
	 vis[vi]=1;
	cout<<vi<<" ";
	p=g->adjlist[vi].fristarc;//找到vi的第一个邻接点

	while(p!=NULL)  //查找vi所有的邻接点
	{
		if(vis[p->adjvex]==0)  //从未被访问过的邻接点出发深度优先搜索
			DFS(g,p->adjvex);
		p=p->next;  //找vi的下一个邻接点
	}
}
void main(void)
{
    /*AdjMatix g;
   CreateMatix(g);
   DispMatix( g);*/


AdjList *g;
 CreateAdjList(g);
DispAdjList(g);
cout<<"广度优先遍历:"<<endl;
BFS(g,0);
cout<<"深度优先遍历:"<<endl;
DFS(g,0);


}

运行结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值