目录
1.利用两种存储方法创建图,实现基本声明。
存储方法有两种
1)邻接矩阵存储方法。
创建图时,我们需要包含的要素有,顶点(结构体),顶点之间的关系(矩阵),边数顶点数常用信息。因此先用一个结构体表示每个单独的顶点(类似链表中会有Node),再用另一个结构体,利用数组包含所有顶点信息,矩阵表示顶点关系,边数顶点数单独表示。代码如下:
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#define InofType char//顶点其它信息
#define MAXV 100//MAXV为最大顶点个数
#define INF 32767//定义无穷
//邻接矩阵存储:n个顶点,n*n型矩阵,i行n列指第i个对第j个之间的关系
//有边记权值,没有边记0
//顶点信息
typedef struct
{
int no;//顶点编号
InofType inof;
}VertexType;
typedef struct
{
VertexType vexs[MAXV];//存放顶点信息
int edges[MAXV][MAXV];//邻接矩阵数组
int n,e;//顶点数,边数
}MatGraph;
2)邻接表存储方法。声明注释如下:
这是一种顺序和链式结合的方法。
链式:每个顶点与之相连的其它顶点之间的关系为链式---边结点,头结点。
顺序:将每个链式之间的头结点用顺序存储,便于查找---头结点用数组存储,便于查找。
//边结点(类似于链表)
typedef struct ANode
{
ANode *nextarc;
int weight;//该条边的权重
int adjvex;//该条边的邻接点编号
}ArcNode;
//头结点
typedef struct Vnode
{
ArcNode*firstarc;//上述边界点链表的头结点
InofType inof;
}VNode;
//图
typedef struct
{
VNode adjlist[MAXV];//头结点
int n,e;//顶点数,边数
}AdjGraph;
2.基本运算算法设计(邻接表)。
1)创建图的运算算法。
void CreatAdj(AdjGraph *G, int A[MAXV][MAXV], int n, int e) {
G = (AdjGraph*)malloc(sizeof(AdjGraph));
for (int i = 0; i < n; i++) {
G->adjlist[i].firstarc = NULL; //将每个链表的头结点指针域置为空
}
ArcNode *p;
for (int i = 0; i < n; i++) {
for (int j = n - 1; j >= 0; j--) { //头插法,倒叙
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->e = e;
G->n = n;
}
2)输出图的运算算法。
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");
}
}
3)销毁图的运算算法。
void DestoryGraph(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 = pre->nextarc;
}
free(pre);
}
}
free(G);//释放头结点
}
完整代码如下:(邻接表存储)
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#define InofType char//顶点其它信息
#define MAXV 100//MAXV为最大顶点个数
/*
#define INF 32767//定义无穷
//邻接矩阵存储:n个顶点,n*n型矩阵,i行n列指第i个对第j个之间的关系
//有边记权值,没有边记0
//顶点信息
typedef struct
{
int no;//顶点编号
InofType inof;
}VertexType;
typedef struct
{
VertexType vexs[MAXV];//存放顶点信息
int edges[MAXV][MAXV];//邻接矩阵数组
int n,e;//顶点数,边数
}MatGraph;
*/
//边结点(类似于链表)
typedef struct ANode {
struct ANode *nextarc;
int weight;//该条边的权重
int adjvex;//该条边的邻接点编号
} ArcNode;
//头结点
typedef struct Vnode {
ArcNode*firstarc;//上述边界点链表的头结点
InofType inof;
} VNode;
//图
typedef struct {
VNode adjlist[MAXV];//头结点
int n, e; //顶点数,边数
} AdjGraph;
void CreatAdj(AdjGraph *&G, int A[MAXV][MAXV], int n, int e) {
G = (AdjGraph*)malloc(sizeof(AdjGraph));
for (int i = 0; i < n; i++) {
G->adjlist[i].inof = 'A' + i;
G->adjlist[i].firstarc = NULL; //将每个链表的头结点指针域置为空
}
ArcNode *p;
for (int i = 0; i < n; i++) {
for (int j = n - 1; j >= 0; j--) { //头插法,倒叙
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->e = e;
G->n = n;
}
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 DestoryGraph(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 = pre->nextarc;
}
free(pre);
}
}
free(G);//释放头结点
}
int main() {
int A[MAXV][MAXV];
memset(A, 0, sizeof(A));
A[0][1] = 2; //给矩阵A赋一些有意义的值,表示图的连接情况和权重
A[0][2] = 4;
A[1][2] = 3;
A[2][0] = 5;
A[2][1] = 6;
AdjGraph *G;
CreatAdj(G, A, 3, 5);
DispAdj(G);
DestoryGraph(G);
return 0;
}
参考书籍:李春葆《数据结构教程第六版》