在数学中,图是描述于一组对象的结构,其中某些对象对在某种意义上是“相关的”。这些对象对应于称为顶点的数学抽象(也称为节点或点),并且每个相关的顶点对都称为边(也称为链接或线)。通常,图形以图解形式描绘为顶点的一组点或环,并通过边的线或曲线连接。 图形是离散数学的研究对象之一。 ------百度百科
图:记为 G=( V, E )
其中:V 是G的顶点集合,是有穷非空集;
E 是G的边集合,是有穷集
下面结论面介绍:图的数组表示法(邻接矩阵)和链式表示法(邻接表)
直接给出存储结构代码
#define MAX_VERTEX_NUM 100 /*最大顶点数设为100*/
/*---图的邻接矩阵表示---*/
typedef struct
{
int vexs[MAX_VERTEX_NUM]; /*顶点向量*/
int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*邻接距阵*/
int vexnum,arcnum; /*顶点数和边数*/
int kind; /*---图的类型(1:有向图 0:无向图)---*/
}Mgraph;
给出边的矩阵表示形式
记住以上规律,对于有向图和无向图的创建,有很大帮助
/*-------------- 图的邻接表--------*/
#define MAX_VERTEX_NUM 100
typedef struct ArcNode{
int adjvex; //该弧所指向的顶点位置
struct ArcNode *nextarc; //指向下一条弧的指针
int weight;
}ArcNode; //表结点 (狐)
typedef struct VNode{
int data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的弧的指针
}VNode; //顶点
typedef struct {
Vnode adjlist [MAX_VERTEX_NUM]; /*邻接表*/
int vexnum,arcnum; //顶点数,边数
int kind;
}ALGraph; //图的邻接表
遍历定义:从已给的图中某一顶点出发,沿着一些边,访遍图中所有的顶点,且 使每个顶点仅被访问一次,就叫做图的遍历。
遍历实质:找每个顶点的邻接点的过程。
图的特点:图中可能存在回路,且图的任一顶点都可能与其它顶点相通,在访问完某个顶点之后可能会沿着某些边又回到了曾经访问过的顶点。
解决思路:可设置一个辅助数组 visited [n ],用来标记每个被访问过的顶点。它的初始状态为0,在图的遍历过程中,一旦某一个顶点i 被访问,就立即改 visited [i]为1,防止它被多次访问。
图的常用遍历方式:1.深度优先搜索 2.广度优先搜索
深度优先遍历(Depth First Search),也有称为深度优先搜索,简称为DFS。
其原理如下:
不难从文字中看出,这是一个递归思想。
给出代码(邻接矩阵):
void DFS( Mgraph g,int v,int visited[])
{/* 邻接矩阵存储,从顶点v出发,对图g进行深度优先搜索*/
int j;
printf("%d ",g.vexs[v]);
visited[v]=1; /*标识v被访问过*/
for(j=0;j
给出代码(邻接表):
void DFS(ALGraph *g,int v,int visited[])
{/*从顶点v出发,对图g进行深度优先搜索*/
ArcNode *p;
int w;
printf("%d ",g->adjlist[v].data);
visited[v]=1; /*标识v被访问过*/
p=g->adjlist[v].firstarc; /*p指向第v个单链表的头指针*/
while(p)
{
w=p->adjvex; /*w为v的邻接点*/
if(visited[w]==0) /*若w未被访问*/
DFS(g,w,visited); /*从w出发递归调用DFS*/
p=p->nextarc; /*找v的下一个邻接点*/
}/*while*/
}/*DFS*/
void DFSTraverse(ALGraph *g)
{ /*邻接表 深度优先搜索*/
int v;
int visited[MAX_VERTEX_NUM];
for(v=0;vvexnum;v++)
visited[v]=0; /*初始化visited数组*/
for(v=0;vvexnum;v++)
if(visited[v]==0) DFS(g,v,visited);
/*从未被访问过的v出发,DFS搜索*/
}
DFS算法是一个递归算法,需要借助一个递归工作栈,故其空间复杂度为O ( V ) O(V)O(V)。
对于n个顶点e条边的图来说,邻接矩阵由于是二维数组,要查找每个顶点的邻接点需要访问矩阵中的所有元素,因此都需要O ( V 2 ) O(V^2)O(V 2 )的时间。而邻接表做存储结构时,找邻接点所需的时间取决于顶点和边的数量,所以是O ( V + E ) O(V+E)O(V+E)。 显然对于点多边少的稀疏图来说,邻接表结构使得算法在时间效率上大大提高。
对于有向图而言,由于它只是对通道存在可行或不可行,算法上没有变化,是完全可以通用的。
广度优先遍历(Breadth First Search),又称为广度优先搜索,简称BFS。
基本思想:——仿树的层次遍历过程。
遍历步骤:在访问了起始点v之后,依次访问 v的邻接点;然后再依次(顺序)访问这些点(下一层)中未被访问过的邻接点;直到所有顶点都被访问过为止。
广度优先搜索是一种分层的搜索过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有回退的情况。
因此,广度优先搜索不是一个递归的过程,其算法也不是递归的
给出代码(邻接矩阵):
void BFSTraverse(Mgraph *mgraph, int n)
{
int v,w,u;
int visited[n];
int Q[n+1],r,f; //Q为队列, 其中r,f分别为队尾指针和对头指针
//初始化visited数组和队列
int i;
for(i = 0;ivexnum;v++)
{
if(!visited[v])
{
visited[v] = 1;//默认从v = 0 开始访问(第一访问)
printf("%d ",mgraph->vexs[v]);//打印
Q[r] = v;//入队列
r = (r+1)%(n+1);
while(fvexnum;w++)
{
if(mgraph->arcs[u][w]==1 && visited[w] == 0) //遍历该顶点所有邻接点,找该顶点是否存在没有访问过的邻接点
{//找到并输出 和入队
visited[w] = 1;
printf("%d ",mgraph->vexs[w]);
Q[r] = w;r = (r+1)%(n+1);
}
}
}
}
}
}
给出代码(邻接表):
void BFSTraverse(ALGraph *g ,int n)
{
int v,w,u;
int Q[n+1];
int visited[g->vexnum];
int r = 0 ,f = 0;
ArcNode *p;
for(int i = 0;ivexnum;v++) visited[v]=0 ;//初始化visited数组
//队列Q初始化
for(v=0;vvexnum ;v++) //从v出发广度优先搜索
{ if (!visited[v])
{
visited[v]=1;
printf("%d ",v); //输出v
Q[r] = v; r = (r+1)%(n+1); //v入队
while(fr) //队列Q不空
{
u = Q[f]; f = (f+1)%(n+1);// u出队
p=g->adjlist[u].firstarc ;
while(p) //依次访问u的邻接点
{ w=p->adjvex;
if(!visited[w])
{ visited[w]=1;
printf("%d ",w);
Q[r] = w; r = (r+1)%(n+1); //w 入队
}
p=p->nextarc ; //p指向下一个邻接点
}//end of while
}//end of while
}//end of if
}//end of for
}//end of BFSTravers
#include
#include
#include
#define MAX_VERTEX_NUM 100 /*最大顶点数设为100*/
/*---图的邻接矩阵表示---*/
typedef struct
{
int vexs[MAX_VERTEX_NUM]; /*顶点向量*/
int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*邻接距阵*/
int vexnum,arcnum; /*顶点数和边数*/
int kind; /*---图的类型(1:有向图 0:无向图)---*/
}Mgraph;
bool InitMgraph(Mgraph *mgraph,int vexnum,int arcnum,int kind)
{
if(!mgraph)
{
return false;
}
/*---初始化边的一些基本信息---*/
mgraph->vexnum = vexnum;
mgraph->arcnum = arcnum;
mgraph->kind = kind;
int i;
int j;
for(i=0;ivexs[i] = 0;
for(j=0;jarcs[i][j] = 0;
}
}
return true;
}
bool CreatMgraph(Mgraph *mgraph)
{
if(!mgraph)
{
return false;
}
int i,j;
for(i=0;ivexnum;i++)
{
mgraph->vexs[i] = i;
}
int count = 0;
while(countarcnum)
{
scanf("%d,%d",&i,&j);
if(mgraph->kind==0)
{
mgraph->arcs[i][j] = 1;
mgraph->arcs[j][i] = 1;
}
else
mgraph->arcs[i][j] = 1;
count++;
}
return true;
}
void printMgraph(Mgraph *mgraph)
{
printf("++++++++++++++++++++++++\n");
printf("+++++图的基本信息+++++++\n");
printf("+顶点数:%d \n",mgraph->vexnum);
printf("+边数 :%d \n",mgraph->arcnum);
printf("邻接矩阵:\n");
int i;
int j;
for(i = 0;ivexnum;i++)
{
for(j = 0;jvexnum;j++)
{
printf(" %d",mgraph->arcs[i][j]);
}
printf("\n");
}
}
void DFS(Mgraph *m,int i,int visited[])
{
printf("%d",m->vexs[i]);
visited[i] = 1;
for(int j = 0;jvexnum;j++)
{
if(m->arcs[i][j] == 1 && visited[j] == 0)
{
DFS(m,j,visited);
}
}
}
void DFST(Mgraph *m)
{
int visited[m->vexnum];
for(int i = 0;ivexnum;i++)
{
visited[i] = 0;
}
for(int i = 0;ivexnum;i++)
{
if(visited[i]==0)
DFS(m,i,visited);
}
}
void BFST(Mgraph *m)
{
int u,v,w;
int visited[m->vexnum];
int Q[m->vexnum+1];
int r,f;
r = 0; f = 0;
for(int i = 0;ivexnum;i++)
{
visited[i] = 0;
}
for(int i = 0;ivexnum;i++)
{
if(!visited[i])
{
printf("%d",m->vexs[i]);
visited[i] = 1;
Q[r] = i; r = (r+1)%(m->vexnum+1);
while(r!=f)
{
u = Q[f];f = (f+1)%(m->vexnum+1);
for(int j = 0;jvexnum;j++)
{
if(m->arcs[u][j] == 1 && visited[j] == 0)
{
visited[j] = 1;
printf("%d",m->vexs[j]);
Q[r] = j; r = (r+1)%(m->vexnum+1);
}
}
}
}
}
}
int main()
{
Mgraph *m1;
m1 = (Mgraph*)malloc(sizeof(Mgraph));
int num,s,kind;
scanf("%d",&kind);
scanf("%d,%d",&num,&s);
InitMgraph(m1,num,s,kind);
CreatMgraph(m1);
DFST(m1);
BFST(m1);
return 0;
}
### 邻接表(带注释) 点击查看代码
#include
#include
#include
/*-------------- 图的邻接表--------*/
#define MAX_VERTEX_NUM 100
typedef struct ArcNode{
int adjvex; //该弧所指向的顶点位置
struct ArcNode *nextarc; //指向下一条弧的指针
int weight;
}ArcNode; //表结点 (狐)
typedef struct VNode{
int data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的弧的指针
}Vnode; //顶点
typedef struct {
Vnode adjlist [MAX_VERTEX_NUM]; /*邻接表*/
int vexnum,arcnum; //顶点数,边数
int kind;
}ALGraph; //图的邻接表
bool InitALGraph(ALGraph *algmraph,int vexnum,int arcnum,int kind)
{
if(!algmraph)
{
return false;
}
algmraph->vexnum = vexnum;
algmraph->arcnum = arcnum;
algmraph->kind = kind;
for(int i = 0;ivexnum;i++)
{
algmraph->adjlist[i].firstarc = NULL;
algmraph->adjlist[i].data = i;
}
return true;
}
bool CreatALGraph(ALGraph *algraph)
{
if(!algraph)
{
return false;
}
int count = 0;
ArcNode *p;
int i,j;
while(countarcnum)
{
scanf("%d,%d",&i,&j);
p = (ArcNode *)malloc(sizeof(ArcNode));
p->adjvex = j;
p->nextarc = algraph->adjlist[i].firstarc;
algraph->adjlist[i].firstarc = p;
if(algraph->kind==0)
{
p = (ArcNode *)malloc(sizeof(ArcNode));
p->adjvex = i;
p->nextarc = algraph->adjlist[j].firstarc;
algraph->adjlist[j].firstarc = p;
}
count++;
}
return true;
}
void printALGraph(ALGraph *algraph)
{
printf("++++++++++++++++++++++++++\n");
printf("+边数:%d 定点数:%d+\n",algraph->vexnum,algraph->arcnum);
printf("邻接表:\n");
ArcNode *p;
for(int i = 0;ivexnum;i++)
{
p = algraph->adjlist[i].firstarc;
while(p!=NULL)
{
printf("(%d,%d) ",i,p->adjvex);
p = p->nextarc;
}
printf("\n");
}
}
void DFS(ALGraph *m,int i, int visited[])
{
ArcNode *p;
printf("%d",m->adjlist[i].data);
p = m->adjlist[i].firstarc;
visited[i] = 1;
while(p)
{
if(visited[p->adjvex] == 0)
{
DFS(m,p->adjvex,visited);
}
p = p->nextarc;
}
}
void DFST(ALGraph *m)
{
int visited[m->vexnum];
for(int i = 0;ivexnum;i++) visited[i] = 0;
for(int i = 0;ivexnum;i++)
{
if(!visited[i])
{
DFS(m,i,visited);
}
}
}
void BFST(ALGraph *m)
{
int Q[m->vexnum+1];
int r,f;
r = 0;f = 0;
int w;
ArcNode *p;
int visited[m->vexnum];
for(int i = 0;ivexnum;i++) visited[i] = 0,Q[i] = 0;
for(int i = 0;ivexnum;i++)
{
if(!visited[i])
{
printf("%d",i);
Q[r] = i;r = (r+1)%(m->vexnum+1);
visited[i] = 1;
while(r!=f)
{
w = Q[f];f = (f+1)%(m->vexnum+1);
p = m->adjlist[w].firstarc;
while(p)
{
if(!visited[p->adjvex])
{
printf("%d",m->adjlist[p->adjvex].data);
Q[r] = p->adjvex;r = (r+1)%(m->vexnum+1);
visited[p->adjvex] = 1;
}
p = p->nextarc;
}
}
}
}
}
int main()
{
ALGraph *al;
al = (ALGraph*)malloc(sizeof(ALGraph));
int kind;
scanf("%d",&kind);
int i,j;
scanf("%d,%d",&i,&j);
InitALGraph(al,i,j,kind);
CreatALGraph(al);
DFST(al);
BFST(al);
printALGraph(al);
return 0;
}