目录
图的基本概念
线性结构:惟一前驱,唯一后继,反映一种线性关系
树型结构:唯一前驱,多个后继,反映一种层次关系
图形结构:不限制前驱和后继的个数,反映一网状关系
图的定义
由一个非空顶点集合和一个描述顶点之间多对关系的边集合组成图=(V,E)
- V表示顶点集合
V(G)
- E表示边集合
E(G)
- 有向边:有弧尾和弧头
<Vi,Vj>
- 无向边:无序
(Vi,Vj)
V(G)={v1,v2,v3,v4}
E(G)={<v1,v2>,<v1,v3>,<v2,v4>,<v3,v2>}
完全图
- 无向完全图
- 有向完全图
度,入度,出度
- 度:与该顶点相关联边的数目
- 入度:有向图中以顶点为终点的边的数目
- 出度:有向图中以顶点为始点的边的数目
子图
路径
- 简单路径:一条路径上除了起点v和终点u相同外,其余顶点均不相同
- 简单回路/简单环:起点和终点相同的简单路径
连通图与强连通图
- 连通图:无向图任意两个不同顶点都有连通
- 强连通图:有向图任意两个不同顶点都存在首尾连接
- 非连通图有多个分量
网络
- 权 :在图的边上附上相关的数值
- 网络:将图的每条边都赋上一个权,则称这种带权图为网络
图的基本运算
图的存储结构
要求编号为i的顶点的度,就是求这个矩阵的第i行的1的个数
有向图想求第i个顶点的入度,就是求第i列1的个数
网络的邻接矩阵
图的邻接矩阵存储结构
图的邻接表存储结构
- 无向图
- 有向图:出边表(邻接表)入边表(逆邻接表)
图的邻接多重表存储结构
图的遍历
图的深度优先遍历(类似于树的前驱遍历)
#include "lib.h"
int visited[M];//作为标识判断结点是否被访问
void dfs(LinkedGraph g,int i)
{
EdgeNode *p;//边结构体
printf("visit vertex:%c\n",g.adjlist[i].vertex);//顶点信息
//访问顶点
visited[i]=1;
p=g.adjlist[i].FirstEdge;//存放头结点的顺序表 邻接链表头指针
while(p)
{
if(!visited[p->adjvex])//未被标识则循环,邻接点
dfs(g,p->adjvex);
p=p->next;
}
}
//深度优先遍历图
//对于整个图来说有可能存在多个连通
void DfsTraverse(LinkedGraph g)
{
int i;
for(i=0;i<g.n;i++)//n表示顶点树,初始化标志数组
visited[i]=0;
for(i=0;i<g.n;i++)
if!visited[i])//未被访问
dfs(g,i);
}
图的广度优先遍历算法
- 全局标识数组
- 临表连接存储结构
#include "ljb.h"
int visited[M];//全局变量标识
void bfs(LinkedGraph g,int i)
{
int j;
EdgeNode *p;
int quene[M],front,rear//顺序表
front=rear=0;//初始化空队列
printf("%c",g.adjlist[i].vertex);//顶点信息
//访问顶点
visited[i]=1;
quene[rear++]=i;//进队
while(rear>front)//当队列非空
{
j=quene[front++];//出队
p=g.adjlist[j].FirstEdge;//存放头结点的顺序表 邻接链表头指针
while(p)
{
if(visited[p->adjvex]==0)
{
printf("%c",g.adjlist[p->adjvex].vertex);
quene[rear++]=p->adjvex;
visited[p->adjvex]=1;
}
p=p->next;
}
}
}
int BfsTraverse(LinkedGraph g)
{
int i,count=0;
for(i=0;i<g.n;i++)//n表示顶点树,初始化标志数组
visited[i]=0;
for(i=0;i<g.n;i++)
if!visited[i])//未被访问
{
printf("\n");
count++;
bfs(g,i);
}
return count;
}