1、类型声明
邻接矩阵
#define MAXV<最大顶点个数>
#define INF 32767 //定义∞
typedef struct
{
int no; //顶点编号
InfoType info; //顶点其他信息
}VertexType; //顶点类型
typedef struct
{
int edges[MAXV][MAXV]; //邻接矩阵数组
int n,e; //顶点数,边数
VertexType vexs[MAXV]; //存放顶点信息
}MatGraph; //邻接矩阵类型
邻接表
typedef struct ANode
{
int adjvex; //该边的邻接点编号
struct ANode *nextarc; //指向下一条边的指针
int weight; //权值
}ArcNode;
typedef struct Vnode
{
InfoType info; //顶点其他信息
ArcNode *firstarc; //指向第一个边结点
}VNode; //邻接表的头结点类型
typedef struct
{
VNode adjlist[MAXV]; //邻接表的头结点数组
int n,e; //顶点数和边数
}AdjGraph; //邻接表类型
2、不带权有向图邻接矩阵
void InDs1(MatGraph g) //求每个顶点的入度
{
int i,j,n;
printf("各顶点入度:\n");
for(j=0;j<g.n;j++)
{
n=0;
for(i=0;i<g.n;i++)
{
if(g.edges[i][j]!=0)
{
n++; //累计入度数
}
}
printf("顶点%d:%d\n",j,n);
}
}
void OutDs1(MatGraph g) //求每个顶点的出度
{
int i,j,n;
printf("各顶点出度:\n");
for(i=0;i<g.n;i++)
{
n=0;
for(j=0;j<g.n;j++)
{
if(g.edges[i][j]!=0)
{
n++; //累计出度数
}
}
printf("顶点%d:%d\n",i,n);
}
}
void ZeroOutDs1(MatGraph g) //求出度为0的顶点
{
int i,j,n;
printf("出度为0的顶点:\n");
for(i=0;i<g.n;i++)
{
n=0;
for(j=0;j<g.n;j++)
{
if(g.edges[i][j]!=0)
{
n++;
}
if(n==0)
{
printf("2d\n",i);
}
}
}
printf("\n");
}
3、不带权有向图邻接表
void InDs2(AdjGraph *G) //求每个顶点的入度
{
ArcNode *p;
int A[MAXV],i; //A存放各顶点的入度
for(i=0;i<G->n;i++) //A中元素初始值0
{
A[i]=0;
}
for(i=0;i<G->n;i++) //扫描所有头结点
{
p=G->adjlist[i].firstarc;
while(p!=NULL) //扫描边结点
{
A[p->adjvex]++; //表示i到p->adjvex顶点有一条边
p=p->nextarc;
}
}
printf("各顶点的入度:\n");
for(i=0;i<G->n;i++)
{
printf("顶点%d:%d\n",i,A[i]);
}
}
void OutDs2(AdjGraph *G) //求每个顶点的出度
{
int i,n;
ArcNode *p;
printf("各顶点出度为:\n");
for(i=0;i<G->n;i++) //扫描所有头结点
{
n=0;
p=G->adjlist[i].firstarc;
while(p!=NULL) //扫描边结点
{
n++;
p=p->nextarc;
}
printf("顶点%d:%d\n",i,n);
}
}
void ZeroOutDs2(AdjGraph *G) //出度为0的顶点数
{
int i,n;
ArcNode *p;
printf("出度为0的顶点数:\n");
for(i=0;i<G->n;i++) //扫描所有头结点
{
n=0;
p=G->adjlist[i].firtarc;
while(p!=NULL) //扫描边结点
{
n++;
p=p->nextarc;
}
if(n==0) //输出出边为0的顶点编号
{
printf("%2d",i);
}
}
printf("\n");
}
4、判断是否存在经过顶点v的回路
int visited[MAXV]; //全局变量数组
void Cycle(AdjGraph *G,int u,int v,int d,bool &has)
{
//调用初始值has置为false,d为-1
ArcNode *p;
int w;
visited[u]=1; //置已访问的标记
d++;
p=G->adjlist[u].firstarc; //p指向顶点u的第一个邻接点
while(p!=NULL)
{
w=p->adjvex;
if(visited[w]==0) //若顶点w未访问,则递归访问
{
Cycle(G,w,v,d,has); //从顶点w出发搜索
}
else if(w==v&&d>1) //u到v存在一条边且回路长度大于1
{
has=true;
return;
}
p=p->nexterc; //找下个邻接点
}
}
bool hasCycle(AdjGraph *G,int v) //判断连通图中是否有经过顶点v的回路
{
bool has=false;
Cycle(G,v,v,-1,has); //从顶点v出发
return has;
}
5、判断无向图是否为一棵树
void DFS(AdjGraph *G,int v,int &vn,int &en)
{
//深度优先遍历图G,并求出遍历过的顶点数vn和边数en
ArcNode *p;
visited[v]=1;
vn++; //遍历过的顶点数增1
p=G->adjlist[v].firstarc;
while(p!=NULL)
{
en++; //遍历过的边数增1
if(visited[p->adjvex]==0)
{
DFS(G,p->adjvex,vn,en);
}
p=p->nextarc;
}
}
bool isTree(AdjGraph *G) //判断无向图G是否为树
{
int vn=0,en=0,i;
for(i=0;i<G->n;i++)
{
visited[i]=0;
}
DFS(G,1,vn,en);
//遍历顶点为 G->n 个,遍历边数为 2(G->n-1),则为树
if(vn==G->n&&en==2*(G->n-1))
{
return true;
}
else
{
return false;
}
}
6、源点到其余各点的最短路径
void shortPath(AdjGraph *G,int i)
{
int qu[MAXV],level[MAXV];
int fornt=0,raer=0,k,lev; //lev保存i到访问顶点的层数
ArcNode *p;
visited[i]=1; //i已经访问,进队
rear++;
qu[rear]=i;
level[rear]=0;
while(front!=rear) //队非空
{
front=(front+1)%MAXV;
//出队
k=qu[front];
lev=level[front];
if(k!=i)
{
printf(" 顶点%d到顶点%d的最短距离是:%d\n",i,k,lev);
}
p=G->adjlist[k].firstarc; //取k的边表头指针
while(p!=NULL) //依次搜索邻接点
{
if(visited[p->adjvex==0]) //未被访问过
{
visited[p->adjvex]=1;
rear=(rear+1)%MAXV;
qu[rear]=p->adjvex; //访问过的邻接点进队
level[rear]=lev+1;
}
p=p->nextarc; //顶点i的下一个邻接点
}
}
}
7、所有路径及其长度
int visited[MAXV];
void findPath(AdjGraph *G,int u,int v,int path[],int d,int length)
{
//d表示 path 中顶点个数,初始为 0;length 表示路径长度,初始为 0
int w,i;
ArcNode *p;
//顶点u加到路径中,d增1
path[d]=u;
d++;
visited[u]=1; //置已访问标记
if(u==v&&d>0) //找到一条路径就输出
{
printf(" 路径长度:%d,路径:",length);
for(i=0;i<d;i++)
{
printf("%2d",path[i]);
}
printf("\n");
}
p=G->adjlist[u].firstarc; //p指向顶点u的第一个邻接点
while(p!=NULL)
{
w=p->adjvex; //w为顶点u的邻接点
if(visited[w]==0) //w未访问,递归访问
{
findPath(G,w,v,path,d,p->weigth+length);
}
p=p->nextarc; //p指向顶点u的下一个邻接点
}
visited[u]=0; //重置
}