定义:
图是由由顶点的有穷非空集合和顶点之间边的集合组成,可以定义为:
G=(V, E)
其中,
V = {x|x∈某个数据元素集合}
E ={(x,y)|x,y∈V} 或
E = {<x, y>|x,y∈V并且Path(x, y)}
其中,(x,y)表示从 x到 y的一条双向通路,即(x,y)是无方向的;Path(x,y)表示从 x到 y的一条单向通路,即Path(x,y)是有方向的。
简单来说:G是图,V是图中顶点的集合,E是图中边的集合
特点:
在线性表中,每个元素之间只有一个直接前驱和一个直接后继,
在树形结构中,数据结构是层次关系,并且每一层上的数据可能和下一层中多个元素相关,但只能和上一层中一个元素相关
非线性结构,是研究数据元素之间的多对多的关系。在这种结构中,任意两个元素之间可能存在关系。即结点之间的关系可以是任意的,图中任意元素之间都可能相关
基本术语
在图中的数据元素,我们称之为顶点(Vertex)
顶点之间的逻辑关系用边来表示,边集可以是空的
若顶点之间的边没有方向,则称这条边为无向边,用无序偶()来表示
图中的每一条边都是没有方向的
若顶点之间的边有方向,则称这条边为有向边,也称为弧(Arc),用有序偶<>来表示,称为弧尾,称为弧头
图中的每一条边都是有方向的
在图结构中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图
在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。含有n个顶点的无向完全图有n(n-1)/2条边。
在有向图中,如果任意两个顶点之间都存在互为相反的两条弧,则称该图为有向完全图。含有n个顶点的无向完全图有n(n-1)条边。
通常认为边或弧数小鱼n*logn(n是顶点的个数)的图称为稀疏图,反之称为稠密图。
有些边或弧带有与他相关的数字,这种与图的边或弧相关的数字,称为权
带权的图称为网
假设有两个图,G1=(V1, E1) 和 G2=(V2, E2)。如果V2∈V1 且 E2∈E1,则称G2为G1的子图
邻接矩阵
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#define isLetter(a) ((((a)>='a')&&((a)<='z')) || (((a)>='A')&&((a)<='Z')))
#define LENGTH(a) (sizeof(a)/sizeof(a[0]))
typedef char vertexType;
typedef int edgeType;
typedef struct _GraphMatrix{
int vertexNumber;// 顶点数
int edgeNumber; // 边数
vertexType *vertex;// 顶点集合
edgeType **edge;// 邻接矩阵
}GraphMatrix;
void Printf_G(GraphMatrix *g){
for(int i=0;i<g->vertexNumber;i++){
for(int j=0;j<g->vertexNumber;j++){
printf("%d\t",g->edge[i][j]);
}
printf("\n");
}
}
void Printf_All(GraphMatrix *g){
int flag=1;
for(int i=0;i<g->vertexNumber;i++){
if(flag){
printf(" \t");
flag=0;
}
printf("%c\t",g->vertex[i]);
}
printf("\n");
for(int i=0;i<g->vertexNumber;i++){
printf("%c\t",g->vertex[i]);
for(int j=0;j<g->vertexNumber;j++){
printf("%d\t",g->edge[i][j]);
}
printf("\n");
}
}
/*
* 返回ch在matrix矩阵中的位置
*/
int Get_Position(GraphMatrix g, char ch){
int i;
for(i=0; i<g.vertexNumber; i++){
if(g.vertex[i]==ch)
return i;
}
return -1;
}
/*
* 读取一个输入字符
*/
char Read_Char(){
char ch;
do {
ch = getchar();
} while(!isLetter(ch));
return ch;
}
void Init_GraphMatrix(GraphMatrix *g){
//初始化图
int v,e;
printf("请输入顶点数量:");
scanf("%d",&v);
printf("请输入边数量:");
scanf("%d",&e);
if ( v < 1 || e < 1 || (e > (v * (v-1)))){
printf("输入参数有误!\n");
exit(0);
}
g->vertexNumber=v;
g->edgeNumber=e;
//分配空间
g->vertex=(vertexType*)malloc(g->vertexNumber*sizeof(vertexType));
// 初始化"边"
g->edge=(edgeType**)malloc(g->vertexNumber*sizeof(edgeType));
for(int i=0;i<g->vertexNumber;i++){
g->edge[i]=(edgeType*)malloc(g->vertexNumber*sizeof(edgeType));
for(int j=0;j<g->vertexNumber;j++){
g->edge[i][j]=0;
}
}
printf("初始化完毕\n");
Printf_G(g);
}
GraphMatrix* Create_GraphMatrix(){
char c1, c2;
int p1, p2;
GraphMatrix *g;
if ((g=(GraphMatrix*)malloc(sizeof(GraphMatrix))) == NULL )
return NULL;
memset(g, 0, sizeof(GraphMatrix));
Init_GraphMatrix(g);
for (int i = 0; i < g->vertexNumber; i++){
printf("请输入顶点(%d)的值: ", i);
g->vertex[i] = Read_Char();
}
for (int i = 0; i < g->edgeNumber; i++){
// 读取边的起始顶点和结束顶点
printf("请输入边(%d)起始顶点和结束顶点:", i);
c1 = Read_Char();
c2 = Read_Char();
p1=Get_Position(*g, c1);
p2=Get_Position(*g, c2 );
if (p1==-1 || p2==-1){
printf("输入有误: 无效的边!\n");
free(g);
exit(0);
}
g->edge[p1][p2]=1;
g->edge[p2][p1]=1;
}
Printf_All(g);
return g;
}
int main()
{
GraphMatrix *gm=Create_GraphMatrix();
return 0;
}
邻接表
#include <stdio.h>
#include <stdlib.h>
typedef char vertexType;
typedef struct ListEdgeNode{
int index; // 边的下标
struct ListEdgeNode *next; // 指向下一个节点的指针
}ListEdgeNode;
typedef struct ListVertexNode {
vertexType vertex; // 顶点
ListEdgeNode *fistEdge; // 指向第一条边
} ListVertexNode;
typedef struct GraphList{
int vertexNumber; // 顶点的数量
int edgeNumber; // 边的数量
ListVertexNode *vertex; // 顶点集合,动态数组
}GraphList;
void GraphList_create(GraphList *g){
printf("请分别输入图的顶点数量和边的数量,用空格隔开:");
scanf("%d %d", &g->vertexNumber, &g->edgeNumber); //将顶点数量和边的数量存储在结构体g中相应的变量
//为动态数组申请空间
g->vertex = (ListVertexNode*)malloc(g->vertexNumber * sizeof(ListVertexNode));
//初始化顶点指的第一条边
for (int i = 0; i < g->edgeNumber; i++){
g->vertex[i].fistEdge = NULL;
}
//输入图的信息
ListEdgeNode *listEdgeNode;
for (int k = 0; k < g->edgeNumber; k++){
int i, j;
printf("请输入边(vi,vj)的下标, i和j,用空格隔开:");
scanf("%d%d", &i, &j);
//始终将插入的节点放在顶点所指的地一条边
listEdgeNode = (ListEdgeNode *)malloc(sizeof(ListEdgeNode));
listEdgeNode->index = j;
listEdgeNode->next = g->vertex[i].fistEdge;
g->vertex[i].fistEdge = listEdgeNode;
listEdgeNode = (ListEdgeNode*)malloc(sizeof(ListEdgeNode));
listEdgeNode->index = i;
listEdgeNode->next = g->vertex[j].fistEdge;
g->vertex[j].fistEdge = listEdgeNode;
}
//输出图的信息
ListEdgeNode * len = NULL;
for (int i = 0; i < g->vertexNumber; i++){
if (g->vertex[i].fistEdge != NULL)
len = g->vertex[i].fistEdge;
while (len!= NULL){
printf("%d --- %d\t", i,len->index);
len = len->next;
}
printf("\n");
}
网友评论