图的定义和术语
- 弧头–弧尾–弧--有向图
- 边–无向图–网--子图
- 完全图–稀释图–稠密图假设图中有n个顶点,e条边:1.含有e=n(n-1)/2条边的无向图称作完全图; 2.含有e=n(n-1)条弧的有向图称作有向完全图; 3.若边或弧的个数e<nlog2n,则称作稀疏图, 否则称作稠密图。
- 邻接点–度--入度–出度
- 路径–路径长度–简单路径–简单回路:1.路径上边的数目称作路径长度;2.若序列中的顶点不重复出现,则称作简单路径;3.若u=w,则称这条路径为回路或简单回路。
- 连通图–连通分量–强连通图–强连通分量:若无向图为非连通图,则图中各个极大连通子图称作此图的连通分量。—— 任何图的连通分量只有一个。
- 生成树–生成森林。
图的存储结构
- 邻接矩阵–顺序存储。
源代码:
#include<stdio.h>
#include<stdlib.h>
#define MAX 20
typedef enum{DG,DN,UDG,UDN}GraphKind;
typedef struct arccell
{
int adj;
char *info;
}ArcCell,AdjMatrix[MAX][MAX];
typedef struct
{
int vexs[MAX];
AdjMatrix arcs;
int vexnum,arcnum;
GraphKind kind;
}MGraph,*pMGraph;
int Locatevex(pMGraph G,int v)//定位元素在一维数组的位置
{
int i;
for(i=0;i<G->vexnum;i++)//寻找位于一维数组的哪个位置
{
if(G->vexs[i]==v)
{
return i;//返回该位置
}
}
if(i==G->vexnum)
{
return -1;//不存在该数据
}
}
void CreateDG(pMGraph G)//构造有向图
{
int i,j;
int v1,v2;
int n,m;
printf("Please input the vexnum,arcnum\n");
scanf("%d,%d",&(G->vexnum),&(G->arcnum));//输入图的顶点数和弧度
printf("Please input the data of vex:\n");
for(i=0;i<G->vexnum;i++)
{
printf("%d. ",i+1);
scanf("%d",&(G->vexs[i]));//输入数据
}
for(i=0;i<(G->vexnum);i++)//清空二维数组
{
for(j=0;j<(G->vexnum);j++)
{
G->arcs[i][j].adj=0;
G->arcs[i][j].info=NULL;
}
}
for(i=0;i<G->arcnum;i++)//输入数据
{
printf("Please input the v1,v2.\n");
scanf("%d,%d",&v1,&v2);//输入弧头和弧尾
n=Locatevex(G,v1);//定位
m=Locatevex(G,v2);//定位
if(m==-1||n==-1)
{
printf("no this vertex");
return;
}
else
{
G->arcs[n][m].adj=1;//连接
}
}
}
void CreateDN(pMGraph G)//构造无向图
{
int i,j;
int v1,v2;
int n,m;
scanf("%d,%d",&(G->vexnum),&(G->arcnum));
printf("Please input the data of vex:\n");
for(i=0;i<G->vexnum;i++)
{
printf("%d. ",i+1);
scanf("%d",&(G->vexs[i]));//输入数据
}
for(i=0;i<(G->vexnum);i++)//清空二维数组
{
for(j=0;j<(G->vexnum);j++)
{
G->arcs[i][j].adj=0;
G->arcs[i][j].info=NULL;
}
}
for(i=0;i<G->arcnum;i++)//输入数据
{
printf("Please input the v1,v2.\n");
scanf("%d,%d",&v1,&v2);//输入弧头和弧尾
n=Locatevex(G,v1);//定位
m=Locatevex(G,v2);//定位
if(m==-1||n==-1)
{
printf("no this vertex");
return;
}
else
{
G->arcs[n][m].adj=1;//连接
G->arcs[m][n].adj=1;//对称
}
}
}
void CreateUDG(pMGraph G)//构造有向网
{
int i,j;
int v1,v2;
int n,m,w;
printf("Please input the vexnum,arcnum\n");
scanf("%d,%d",&(G->vexnum),&(G->arcnum));//输入图的顶点数和弧度
printf("Please input the data of vex:\n");
for(i=0;i<G->vexnum;i++)
{
printf("%d. ",i+1);
scanf("%d",&(G->vexs[i]));//输入数据
}
for(i=0;i<(G->vexnum);i++)//清空二维数组
{
for(j=0;j<(G->vexnum);j++)
{
G->arcs[i][j].adj=0;
G->arcs[i][j].info=NULL;
}
}
for(i=0;i<G->arcnum;i++)//输入数据
{
printf("Please input the v1,v2,w.\n");
scanf("%d,%d,%d",&v1,&v2,&w);//输入弧头和弧尾
n=Locatevex(G,v1);//定位
m=Locatevex(G,v2);//定位
if(m==-1||n==-1)
{
printf("no this vertex");
return;
}
else
{
G->arcs[n][m].adj=w;//连接
}
}
}
void CreateUDN(pMGraph G)//构造无向网
{
int i,j;
int v1,v2;
int n,m,w;
printf("Please input the vexnum,arcnum\n");
scanf("%d,%d",&(G->vexnum),&(G->arcnum));//输入图的顶点数和弧度
printf("Please input the data of vex:\n");
for(i=0;i<G->vexnum;i++)
{
printf("%d. ",i+1);
scanf("%d",&(G->vexs[i]));//输入数据
}
for(i=0;i<(G->vexnum);i++)//清空二维数组
{
for(j=0;j<(G->vexnum);j++)
{
G->arcs[i][j].adj=0;
G->arcs[i][j].info=NULL;
}
}
for(i=0;i<G->arcnum;i++)//输入数据
{
printf("Please input the v1,v2,w.\n");
scanf("%d,%d,%d",&v1,&v2,&w);//输入弧头和弧尾
n=Locatevex(G,v1);//定位
m=Locatevex(G,v2);//定位
if(m==-1||n==-1)
{
printf("no this vertex");
return;
}
else
{
G->arcs[n][m].adj=w;//连接
G->arcs[m][n].adj=w;//连接
}
}
}
void CreateGraph(pMGraph G)//选择图的类型
{
printf("Please input the option:\n");
printf("1.DG\t2.DN\t3.UDG\t4.UDN\n");
scanf("%d",&(G->kind));
switch(G->kind)
{
case DG:
return CreateDG(G);
break;
case DN:
return CreateDN(G);
break;
case UDG:
return CreateUDG(G);
break;
case UDN:
return CreateUDN(G);
break;
default:
break;
}
}
void Print(pMGraph G)
{
int i,j;
for(i=0;i<G->vexnum;i++)
{
for(j=0;j<G->vexnum;j++)
{
printf("%d",G->arcs[i][j].adj);
}
printf("\n");
}
}
int main() {
MGraph G;//建立一个图的变量
CreateGraph(&G);//调用创建函数,传入地址参数
Print(&G);//输出图的二阶矩阵
return 0;
}
- 链式存储
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
typedef enum{DG=1,AG,WDG,WAG}GraphKind;//有向图 无向图 带权有向图 带权无向图
typedef struct ArcNode
{
int adjvex;//该弧所指向的位置
struct AtcNode*nextarc;//指向下一条弧的指针
int *info;//该弧的相关信息
}ArcNode,*pArcNode;
typedef struct VNode
{
int data;//结点信息
int indegree;//顶点的度
pArcNode firstarc;//指向下一条边
}VNode,AdjList[MAX];
typedef struct
{
AdjList vertices;//顶点信息数组
int vexnum,arcnum;//顶点数和弧度数
GraphKind kind;//图的种类
}GraphList,*pGraphList;
void CreateGraph(pGraphList G);//建立有向图
int LocateVex(pGraphList G,int v);//定位结点位置
void InsertVex(pGraphList G,int v);//插入结点
void InsertArc(pGraphList G);//插入弧
int main()
{
printf("Hello world!\n");
return 0;
}
void CreateGraph(pGraphList G)
{
pGraphList G;
int i;//循环变量
int op=0;
printf("1.DG\t2.AG\t3.WDG\t4.WAG\n");
printf("which graph you want:\t");
switch(op)//选择创建哪个图
{
case 1:
G->kind=DG;
break;
case 2:
G->kind=AG;
break;
case 3:
G->kind=WDG;
break;
case 4:
G->kind=WAG;
break;
default:
printf("ERROR!");
break;
}
G->vexnum=0;
for(i=0;i<MAX;i++)//对图进行格式化
{
G->vertices[i].data=0;
G->vertices[i].indegree=0;
G->vertices.firstarc=NULL;
}
return G;//返回图
}
int LocateVex(pGraphList G,int v)
{
int i;
for(i=0;i<G->vexnum;i++)//循环查找结点位置
{
if(v==(G->vertices[i].data))
{
return i;//返回结点位置
}
}
if(i==G->vexnum)//结点不存在返回-1
{
return -1;
}
}
void InsertVex(pGraphList G,int v)
{
if((G->vexnum+1)>MAX)//判断是否超出最大值
{
printf("The elem can not be more!");
}
else//存入数据结点
{
G->vertices[G->vexnum].data=v;
G->vertices[G->vexnum].firstarc=NULL;
G->vexnum++;
printf("Insert success!");
}
}
void InsertArc(pGraphList G)
{
if(G->kind==DG)//构造有向图
{
int head,tail;
pArcNode r1,r2;
printf("please input the head of arc:\t");
scanf("%d",&head);
getchar();
printf("please input the tail of ars:\t");
scanf("%d",&tail);
getchar();
if(tail<G->vexnum&&head<G->vexnum)
{
r1=(pArcNode)malloc(sizeof(ArcNode));
r1->adjvex=tail;
r1->info=0;
r1->nextarc=G->vertices[head].firstarc;
G->vertices[head].firstarc=r1;
G->vexnum++;
printf("insert success!");
}
else
{
printf("insert fail!");
}
}
}