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);
}
运行结果: