1. 数组表示法:
#include <stdio.h>
#include <limits.h>
#define INFINITY INT_MAX
#define Maxvex 100
typedef struct graph {
int vexs[Maxvex+1]; //顶点
int AdjMatrix[Maxvex+1][Maxvex+1]; //邻接矩阵
int vexsnum, edgenum; //顶点数,边数
}Graph;
void CreateGraph(Graph *G) {
printf("请输入顶点数,边数:");
scanf("%d %d",&G->vexsnum, &G->edgenum);
for (int i = 1; i <= G->vexsnum; i++) {
scanf("%d",&G->vexs[i]);
for (int j = 1; j <= G->vexsnum; j++) {
G->AdjMatrix[i][j] = INFINITY;
}
}
int row, col, w;
for (int i = 1; i <= G->edgenum; i++) {
printf("输入边坐标i,j,权值:");
scanf("%d%d%d",&row, &col, &w);
G->AdjMatrix[row][col] = w;
G->AdjMatrix[col][row] = w;
}
}
int main () {
Graph G;
CreateGraph(&G);
return 0;
}
2.邻接表
#include <stdio.h>
#include <stdlib.h>
#define Vertex_Num 100
typedef int VertexType;
//存储弧的结点
typedef struct ArcNode {
int adjvex; //该弧所指向的顶点的位置
int info; //该弧的权值
struct ArcNode *next; //指向下一条弧的指针
}ArcNode;
//存储顶点的结点
typedef struct VNode {
VertexType data;
ArcNode *first;//指向第一条依附该顶点的弧的指针
}VNode, AdjList[Vertex_Num];
//图
typedef struct {
AdjList vertices;
int vexnum, arcnum; //图的顶点数和弧数
}Graph;
void CreateGraph(Graph *G) {
printf("请输入顶点数,边数:\n");
scanf("%d %d", &G->vexnum, &G->arcnum);
printf("请输入顶点\n");
for (int i = 1; i <= G->vexnum; i++) {
scanf("%d",&G->vertices[i].data);
G->vertices[i].first = NULL;
}
printf("请选择你要建立的存储类型,1表示邻接表,0表示逆邻接表:\n");
int choice;
scanf("%d",&choice);
int vex1, vex2, weight;
if (choice != 1 && choice != 0) {
printf("输入有错,请重新输入\n");
scanf("%d",&choice);
}
if (choice == 1) {
for (int j =1; j <= G->arcnum; j++) {
printf("请输入边的两个顶点以及权值:\n");
scanf("%d%d%d", &vex1, &vex2, &weight);
ArcNode *edge = (ArcNode*)malloc(sizeof(ArcNode));
edge->adjvex = vex2;
edge->info = weight;
edge->next = G->vertices[vex1].first;
G->vertices[vex1].first = edge;
}
}
if (choice == 0) {
for (int j =1; j <= G->arcnum; j++) {
printf("请输入边的两个顶点以及权值:\n");
scanf("%d%d%d", &vex1, &vex2, &weight);
ArcNode *edge = (ArcNode*)malloc(sizeof(ArcNode));
edge->adjvex = vex1;
edge->info = weight;
edge->next = G->vertices[vex2].first;
G->vertices[vex2].first = edge;
}
}
}
int main()
{
Graph G;
CreateGraph(&G);
for(int i = 1; i <= G.vexnum; i++)
{
printf("|%d|->", G.vertices[i].data);
ArcNode *e = G.vertices[i].first;
while(e != NULL)
{
printf("%d->", e->adjvex);
e = e->next;
}
printf("NULL\n");
}
return 0;
}
运行结果:
- 邻接表:
- 逆邻接表:
3. 十字链表:
#include <stdio.h>
#include <stdlib.h>
// - - - - - 有向图的十字链表存储结构 - - - - -
//相当于把有向图的邻接表和逆邻接表结合到一起得到的一种链表
#define VERTEX_NUM 100
typedef int VertexType;
//弧结点
typedef struct ArcBox {
int tailvex, headvex; //弧头和弧尾的位置
struct ArcBox *hlink, *tlink; //分别指向下一个弧头和弧尾相同的链域
int info; //弧的权值
}ArcBox;
//顶点结点
typedef struct VexNode {
VertexType data;
ArcBox *firstin, *firstout;
}VexNode;
//图
typedef struct {
VexNode xlist[VERTEX_NUM]; //表头向量
int vexnum, arcnum; //有向图的当前顶点数和弧数
}Graph;
void CreateGraph(Graph *G) {
printf("请输入顶点数,弧数:\n");
scanf("%d%d",&G->vexnum, &G->arcnum);
printf("请输入顶点:\n");
for (int i = 1; i <= G->vexnum; i++) {
scanf("%d",&G->xlist[i].data);
G->xlist[i].firstin = NULL;
G->xlist[i].firstout = NULL;
}
int vex1, vex2, weight;
for (int i = 1; i <= G->arcnum; i++) {
printf("请输入弧尾,弧头,弧的权值\n");
scanf("%d%d%d",&vex1, &vex2, &weight);
ArcBox *e = (ArcBox*)malloc(sizeof(ArcBox));
e->tailvex = vex1;
e->headvex = vex2;
e->tlink = NULL;
e->hlink = NULL;
e->tlink = G->xlist[vex1].firstout;
G->xlist[vex1].firstout = e;
e->hlink = G->xlist[vex2].firstin;
G->xlist[vex2].firstin = e;
}
}
4. 邻接多重表:
// - - - - - 图的邻接多重表存储表示 - - - - -
// - - - - - - 更适用于无向图 - - - - - -
// - - 相比邻接表更方便对某一条边进行操作 - -
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define VERTEX_NUM 100
typedef enum {unvisited, visited} VisitIf;
typedef int VertexType;
typedef struct EBox {
VisitIf mark; //访问标记
int ivex, jvex;
struct EBox *ilink, *jlink; //分别指向依附这两个顶点的下一条边
int info; //权值
}EBox;
typedef struct VexBox {
VertexType data;
EBox *firstedge; //指向第一条依附该顶点的边
}VexBox;
typedef struct {
VexBox adjmulist[VERTEX_NUM];
int vexnum, edgenum; //图的顶点数和弧数
}Graph;
void CreateGraph(Graph *G) {
//G = (Graph*)malloc(sizeof(Graph));
printf("请输入点数,弧数\n");
scanf("%d%d",&G->vexnum, &G->edgenum);
printf("请输入顶点\n");
for(int i = 1; i <= G->vexnum; i++) {
scanf("%d",&G->adjmulist[i].data);
G->adjmulist[i].firstedge = NULL;
}
int v1, v2, weight;
for(int k = 1; k <= G->edgenum; k++) {
printf("请输入两个顶点v1,v2以及弧的权值\n");
scanf("%d%d%d",&v1,&v2,&weight);
EBox *edge = (EBox*)malloc(sizeof(EBox));
edge->mark = unvisited;
edge->ivex = v1;
edge->jvex = v2;
edge->info = weight;
edge->ilink = NULL;
edge->jlink = NULL;
EBox *p = G->adjmulist[v1].firstedge;
if (!p) {
G->adjmulist[v1].firstedge = edge;
}
else {
while((p->ilink != NULL && p->ivex == v1) || (p->jlink != NULL && p->jvex == v1)) {
if(v1 == p->ivex)
p = p->ilink;
else
p = p->jlink;
}
if(p->ivex == v1) p->ilink = edge;
else p->jlink = edge;
}
p = G->adjmulist[v2].firstedge;
if (!p) {
G->adjmulist[v2].firstedge = edge;
}
else {
while((p->ilink != NULL && p->ivex == v2) || (p->jlink != NULL && p->jvex == v2)) {
if(v2 == p->ivex)
p = p->ilink;
else
p = p->jlink;
}
if(p->ivex == v2) p->ilink = edge;
else p->jlink = edge;
}
}
}
void PrintGraph(Graph G)
{
EBox *p;
for(int i = 1; i <= G.vexnum; ++i)
{
p = G.adjmulist[i].firstedge;
while(p != NULL)
{
if(p->ivex == i) //判断相等才能知道连接上的是ivex还是jvex;
{
printf("%d--%d\n", G.adjmulist[p->ivex].data, G.adjmulist[p->jvex].data);
p = p->ilink;
}
else
{
printf("%d--%d\n", G.adjmulist[p->jvex].data, G.adjmulist[p->ivex].data);
p = p->jlink;
}
}
}
}
int main () {
Graph G;
CreateGraph(&G);
PrintGraph(G);
return 0;
}
运行结果: