C语言编程求图的邻接矩阵,C语言实现图的邻接矩阵和邻接表存储

C语言实现图的邻接矩阵和邻接表存储,其中包含如下函数:

CreateMat(MatGraph &g, int A[MAXV][MAXV], int n, int e):由边数组A、顶点数n和边数e创建图的邻接矩阵g。

DispMat(MatGraph g):输出邻接矩阵g。

CreateAdj(AdjGraph *& G, int A[MAXV][MAXV], int n, int e):由边数组A、顶点数n和边数e创建图的邻接表G。

DispAdj(AdjGraph *G):输出邻接表G。

DestroyAdj(AdjGraph *&G):销毁图的邻接表G。

对应代码如下:

#include "stdio.h"

#include "malloc.h"

#define INF32767

#define MAXV100

typedef char InfoType;

typedef struct {

intno;

InfoTypeinfo;

} VertexType;

typedef struct {

intedges[MAXV][MAXV];

intn, e;

VertexTypevexs[MAXV];

} MatGraph;

typedef struct ANode {

intadjvex;

struct ANode* nextarc;

intweight;

} ArcNode;

typedef struct Vnode {

InfoTypeinfo;

intcount;

ArcNode* firstarc;

} VNode;

typedef struct {

VNodeadjlist[MAXV];

intn, e;

} AdjGraph;

/*

* -----------------------邻接矩阵的基本运算算法------------------------

* 创建图的邻接矩阵

*/

void CreateMat( MatGraph &g, int A[MAXV][MAXV], int n, int e )

{

int i, j;

g.n= n;

g.e= e;

for ( i = 0; i < g.n; i++ )

for ( j = 0; j < g.n; j++ )

g.edges[i][j] = A[i][j];

}

/* 输出邻接矩阵g */

void DispMat( MatGraph g )

{

int i, j;

for ( i = 0; i < g.n; i++ )

{

for ( j = 0; j < g.n; j++ )

if ( g.edges[i][j] != INF )

printf( "%4d", g.edges[i][j] );

else

printf( "%4s", "∞" );

printf( "\n" );

}

}

/*

* -----------------------邻接表的基本运算算法------------------------

* 创建图的邻接表

*/

void CreateAdj( AdjGraph * & G, int A[MAXV][MAXV], int n, int e )

{

inti, j;

ArcNode *p;

G = (AdjGraph *) malloc( sizeof(AdjGraph) );

for ( i = 0; i < n; i++ )

G->adjlist[i].firstarc = NULL;

for ( i = 0; i < n; i++ )

for ( j = n - 1; j >= 0; j-- )

if ( A[i][j] != 0 && A[i][j] != INF )

{

p= (ArcNode *) malloc( sizeof(ArcNode) );

p->adjvex= j;

p->weight= A[i][j];

p->nextarc= G->adjlist[i].firstarc;

G->adjlist[i].firstarc= p;

}

G->n= n;

G->e= e;

}

/* 输出临界表G */

void DispAdj( AdjGraph *G )

{

ArcNode *p;

for ( int i = 0; i < G->n; i++ )

{

p = G->adjlist[i].firstarc;

printf( "%3d:", i );

while ( p != NULL )

{

printf( "%3d[%d]→", p->adjvex, p->weight );

p = p->nextarc;

}

printf( "∧\n" );

}

}

/* 销毁图的邻接表 */

void DestroyAdj( AdjGraph * &G )

{

ArcNode *pre, *p;

for ( int i = 0; i < G->n; i++ )

{

pre = G->adjlist[i].firstarc;

if ( pre != NULL )

{

p = pre->nextarc;

while ( p != NULL )

{

free( pre );

pre= p;

p= p->nextarc;

}

free( pre );

}

}

free( G );

}

/* --------------main----------------------------- */

int main()

{

MatGraphg;

AdjGraph*G;

intA[MAXV][MAXV] = {

{ 0, 5, INF, 7, INF, INF }, { INF, 0, 4, INF, INF, INF },

{ 8, INF, 0, INF, INF, 9 }, { INF, INF, 5, 0,INF, 6 },

{ INF, INF, INF, 5, 0, INF }, { 3, INF, INF, INF, 1, 0 }

};

intn = 6, e = 10;

CreateMat( g, A, n, e );

printf( "(1)图G的邻接表:\n" );

DispMat( g );

CreateAdj( G, A, n, e );

printf( "(2)图G的邻接表:\n" );

DispAdj( G );

printf( "(3)销毁图G的邻接表\n" );

DestroyAdj( G );

return(1);

}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是使用邻接表邻接矩阵实现的广度遍历和深度遍历的C语言代码示例。 邻接表实现: ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define MAX_VERTEX_NUM 100 // 最大顶点数 // 边结点 typedef struct EdgeNode { int adjvex; // 邻接点的下标 struct EdgeNode* next; // 指向下一个邻接点的指针 } EdgeNode; // 顶点结点 typedef struct VertexNode { int data; // 顶点数据 EdgeNode* firstedge; // 指向第一个邻接点的指针 } VertexNode, AdjList[MAX_VERTEX_NUM]; // 邻接表 typedef struct { AdjList vertices; // 顶点数组 int vexnum, edgenum; // 顶点数和边数 } ALGraph; // 初始化邻接表 void InitALGraph(ALGraph* G) { printf("请输入顶点数和边数:"); scanf("%d%d", &G->vexnum, &G->edgenum); printf("请输入%d个顶点的数据:", G->vexnum); for (int i = 0; i < G->vexnum; i++) { scanf("%d", &G->vertices[i].data); G->vertices[i].firstedge = NULL; } printf("请输入%d条边的信息:\n", G->edgenum); for (int k = 0; k < G->edgenum; k++) { int i, j; printf("请输入第%d条边的两个顶点下标:", k + 1); scanf("%d%d", &i, &j); // 创建新结点 EdgeNode* e = (EdgeNode*)malloc(sizeof(EdgeNode)); e->adjvex = j; e->next = G->vertices[i].firstedge; G->vertices[i].firstedge = e; // 无向还要创建一条反向边 e = (EdgeNode*)malloc(sizeof(EdgeNode)); e->adjvex = i; e->next = G->vertices[j].firstedge; G->vertices[j].firstedge = e; } } // 广度优先遍历 void BFS(ALGraph* G, int v) { bool visited[MAX_VERTEX_NUM] = { false }; // 初始化所有顶点为未访问 int queue[MAX_VERTEX_NUM], front = 0, rear = 0; visited[v] = true; queue[rear++] = v; printf("BFS: "); while (front < rear) { int i = queue[front++]; printf("%d ", G->vertices[i].data); EdgeNode* e = G->vertices[i].firstedge; while (e != NULL) { int j = e->adjvex; if (!visited[j]) { visited[j] = true; queue[rear++] = j; } e = e->next; } } printf("\n"); } // 深度优先遍历(递归版) void DFS(ALGraph* G, int v, bool visited[]) { visited[v] = true; printf("%d ", G->vertices[v].data); EdgeNode* e = G->vertices[v].firstedge; while (e != NULL) { int j = e->adjvex; if (!visited[j]) { DFS(G, j, visited); } e = e->next; } } // 深度优先遍历(非递归版) void DFS2(ALGraph* G, int v) { bool visited[MAX_VERTEX_NUM] = { false }; int stack[MAX_VERTEX_NUM], top = 0; visited[v] = true; stack[top++] = v; printf("DFS: "); while (top > 0) { int i = stack[--top]; printf("%d ", G->vertices[i].data); EdgeNode* e = G->vertices[i].firstedge; while (e != NULL) { int j = e->adjvex; if (!visited[j]) { visited[j] = true; stack[top++] = j; } e = e->next; } } printf("\n"); } int main() { ALGraph G; InitALGraph(&G); BFS(&G, 0); bool visited[MAX_VERTEX_NUM] = { false }; DFS(&G, 0, visited); printf("\n"); DFS2(&G, 0); return 0; } ``` 邻接矩阵实现: ```c #include <stdio.h> #include <stdbool.h> #define MAX_VERTEX_NUM 100 // 最大顶点数 // 邻接矩阵 typedef struct { int edges[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 二维数组表示边 int vexnum, edgenum; // 顶点数和边数 } MGraph; // 初始化邻接矩阵 void InitMGraph(MGraph* G) { printf("请输入顶点数和边数:"); scanf("%d%d", &G->vexnum, &G->edgenum); printf("请输入%d个顶点的数据:", G->vexnum); for (int i = 0; i < G->vexnum; i++) { for (int j = 0; j < G->vexnum; j++) { G->edges[i][j] = 0; // 初始化所有边为0 } } for (int i = 0; i < G->vexnum; i++) { int data; scanf("%d", &data); } printf("请输入%d条边的信息:\n", G->edgenum); for (int k = 0; k < G->edgenum; k++) { int i, j; printf("请输入第%d条边的两个顶点下标:", k + 1); scanf("%d%d", &i, &j); G->edges[i][j] = G->edges[j][i] = 1; // 无向需要将两个方向的边都设置为1 } } // 广度优先遍历 void BFS(MGraph* G, int v) { bool visited[MAX_VERTEX_NUM] = { false }; // 初始化所有顶点为未访问 int queue[MAX_VERTEX_NUM], front = 0, rear = 0; visited[v] = true; queue[rear++] = v; printf("BFS: "); while (front < rear) { int i = queue[front++]; printf("%d ", i); for (int j = 0; j < G->vexnum; j++) { if (G->edges[i][j] == 1 && !visited[j]) { visited[j] = true; queue[rear++] = j; } } } printf("\n"); } // 深度优先遍历 void DFS(MGraph* G, int v, bool visited[]) { visited[v] = true; printf("%d ", v); for (int j = 0; j < G->vexnum; j++) { if (G->edges[v][j] == 1 && !visited[j]) { DFS(G, j, visited); } } } int main() { MGraph G; InitMGraph(&G); BFS(&G, 0); bool visited[MAX_VERTEX_NUM] = { false }; DFS(&G, 0, visited); printf("\n"); return 0; } ``` ### 回答2: 邻接表邻接矩阵是两种常见的的表示方法,可以用于实现的广度遍历和深度遍历的算法。 邻接表是一种链表的形式,用于表示的结构。对于每个顶点,将其邻接的顶点用链表链接起来,形成一个邻接表邻接矩阵则是一个二维矩阵,用于表示的连接关系。 广度遍历(BFS)是从的某个节点出发,先访问其所有邻接节点,再按照广度优先的顺序遍历所有未被访问的邻接节点。具体实现方法如下: 1. 创建一个队列,将起始节点入队。 2. 从队列中取出一个节点,访问该节点并标记为已访问。 3. 遍历该节点的邻接节点,将未被访问的节点入队。 4. 重复步骤2和3,直到队列为空。 深度遍历(DFS)是从的某个节点出发,先访问其一个邻接节点,再依次访问该节点的邻接节点,直到无法继续访问为止,然后回溯到上一个节点,继续访问下一个未被访问的邻接节点。具体实现方法如下: 1. 创建一个栈,将起始节点压栈。 2. 从栈中弹出一个节点,访问该节点并标记为已访问。 3. 遍历该节点的邻接节点,将未被访问的节点压栈。 4. 重复步骤2和3,直到栈为空。 无论使用邻接表还是邻接矩阵都可以实现的广度遍历和深度遍历。对于邻接表,广度遍历可以通过链表的特性实现邻居节点的访问顺序;深度遍历可以通过递归或者栈的方式实现节点的回溯。对于邻接矩阵,广度遍历可以通过遍历矩阵的行实现邻居节点的访问顺序;深度遍历可以通过递归或者栈的方式实现节点的回溯。 综上所述,无论使用邻接表还是邻接矩阵,我们都可以实现的广度遍历和深度遍历的算法。 ### 回答3: 邻接表邻接矩阵是两种常用的存储的方法,它们可以用于实现的广度遍历和深度遍历。 邻接表是一种链表的数据结构,用于表示中各个顶点之间的关系。对于每个顶点,邻接表存储了与之相邻顶点的指针。通过邻接表实现的广度遍历时,可以使用队列来存储待访问的顶点。首先将起始顶点放入队列中,然后依次访问队列中的顶点,并将其未访问过的相邻顶点放入队列中。直到队列为空时,广度遍历结束。 邻接矩阵是一个二维数组,用于表示中各个顶点之间的关系。对于顶点i和顶点j,邻接矩阵中的元素A[i][j]表示它们之间的边。通过邻接矩阵实现的深度遍历时,可以使用递归或栈来存储待访问的顶点。首先将起始顶点放入栈中,然后依次访问栈顶的顶点,并将其未访问过的相邻顶点放入栈中。直到栈为空时,深度遍历结束。 无论使用邻接表还是邻接矩阵的广度遍历和深度遍历的时间复杂度都是O(V+E),其中V为顶点数,E为边数。 邻接表的优点是可以节省空间,适用于稀疏。而邻接矩阵的优点是查找两个顶点之间是否有边的时间复杂度为O(1),适用于稠密。选择哪种方法实现的广度遍历和深度遍历取决于具体问题的要求和的类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值