C语言 图操作--邻接表法
C语言 图操作–邻接表法
这里只是图的创建部分,图的遍历会在后面更新。
一、图的介绍
图是一种相较于链表和树更为复杂的数据结构。在线性表中,数据元素之间仅有线性关系,每个元素只有一个直接前驱和一个直接后继(每个元素之间一个一个逐个相连)。在树形结构中,数据元素之间有着明显的层次关系,上一层元素能和下层多个元素相关,但是下层元素只能与一个上层元素相关。而在图结构中,节点之间的关系任意,任何两个顶点都可能相连。
图结构如图所示
此中为“离散数学”中的图理论。
二、图的术语
接下来介绍图结构中的一些术语。
1.顶点 图中的数据元素通常称为顶点。
2.边 两顶点间的连线称为边。
3.V是顶点的有穷非空集合。
4.VR是两个顶点之间关系的集合,也是边的集合。
5.通常表示为:G(V,E),G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
6.无向边:若顶点A到顶点B的边没有方向,称这条边为无向边,用无序偶对(A,B)或(B,A)表示。
7.有向边:若顶点A到顶点B的边有方向,称这条边为有向边,也称为弧(Arc),用有序对 < B, A >表示;B表示弧尾,A表示弧头
8.由无向边构成的图为无向图
9.由有向边构成的图为有向图
这里只是一些最基本的术语,大家可以自己去看看大佬们的介绍。
三、图结构的构建
1.用邻接表创建图结构既是使用链表记录一个顶点的所有邻近顶点,再用数组存取顶点信息,当然顶点信息也可以用链表串起来。
2.邻接表的结构体定义代码如图所示
void clear() //该函数起到一个清空缓冲区的作用,防止多部输入错误。 { int ch; while ((ch = getchar()) != EOF && ch != '\n') ; } struct Node //定义邻接表的节点属性 { int data;//邻接表的数据域 struct Node *next; //邻接表的指针域 }; struct Head //定义图的顶点的属性 { char info; //存储图顶点信息 struct Node *dajoin; //定义临近顶点指针 }; struct Map //定义图结构 { int side; //记录边的数量 int spot; //记录图的数量 struct Head head[20]; //用数组记录顶点下标 };
3.创建一个图
定义完结构体之后需要创建图结构,并对输入的数据进行存储。将存数据的各个顶点进行关联。
void creat_graph(struct Map *map) { int i, j; char S1 = 0; char S2 = 0; struct Node *p; printf("请输入要建立的顶点数:\n"); scanf("%d", &map->spot);//将输入的顶点数存入图结构体变量中 clear();//清空缓冲区 下同 printf("请输入要建立的边的数:\n"); scanf("%d", &map->side);//将输入的边数存入图结构体变量中 clear(); for (i = 0; i < map->spot; i++) { map->head[i].info = i + 'A';//创建n个顶点并分别赋值为A到i+"A" map->head[i].dajoin = NULL;//初始化顶点,使顶点邻接点为空。 } printf("请输入要建立的边:\n"); for (j = 0; j < map->side; j++) { scanf("%c%c", &S1, &S2); //通过输入字母 如AB BC 建立边并连接顶点 getchar(); if (S1 != ' ' && S2 != ' ' && S1 != S2)//如果s1 s2都不为‘ ’ 且不等。 { insert(map, S1, S2);//把s2顶点挂在s1顶点下。此函数定义后面介绍 } } }
4.邻接表的插入操作。
此步骤与普通的链表插入无不同,如果有不了解的可以区看我前面的博客(记得点赞加关注哦!)。此处不作过多介绍。
void insert(struct Map *map, char S1, char S2) { if (map->head[B1].dajoin != NULL) //如果该顶点下未已挂载链表则进行比较并插入 { if (map->head[B1].dajoin->data > B2) { struct Node *temp = malloc(sizeof(struct Node)); temp->data = B2; temp->next = map->head[B1].dajoin; map->head[B1].dajoin = temp; } else { struct Node *demp = map->head[B1].dajoin; struct Node *before = demp; while (demp && B2 > demp->data) { before = demp; demp = demp->next; } struct Node *emp = malloc(sizeof(struct Node)); emp->data = B2; emp->next = before->next; before->next = emp; } } else //如果未挂载链表则直接挂载链表 { map->head[B1].dajoin = malloc(sizeof(struct Node)); map->head[B1].dajoin->data = B2; map->head[B1].dajoin->next = NULL; } }
5、展现图的结构关系
void print(struct Map *map) { int i; for (i = 0; i < map->spot; i++) //通过循环找到各个顶点之间的连接关系 { char ele = i + 'A'; struct Node *p = map->head[i].dajoin; printf("与%c连接的结点有:", ele); while (p) { char ele = p->data + 'A'; printf("%c ", ele); p = p->next; } printf("\n"); } }
四、完整代码
#include "stdlib.h" #include "stdio.h" #define B1 (S1 - 'A') #define B2 (S2 - 'A') void clear() { int ch; while ((ch = getchar()) != EOF && ch != '\n') ; } struct Node { int data; struct Node *next; }; struct Head { char info; struct Node *dajoin; }; struct Map { int side; int spot; struct Head head[20]; }; void creat_graph(struct Map *map) { int i, j; char S1 = 0; char S2 = 0; struct Node *p; printf("请输入要建立的顶点数:\n"); scanf("%d", &map->spot); clear(); printf("请输入要建立的边的数:\n"); scanf("%d", &map->side); clear(); for (i = 0; i < map->spot; i++) { map->head[i].info = i + 'A'; map->head[i].dajoin = NULL; } printf("请输入要建立的边:\n"); for (j = 0; j < map->side; j++) { scanf("%c%c", &S1, &S2); getchar(); if (S1 != ' ' && S2 != ' ' && S1 != S2) { insert(map, S1, S2); } } } void insert(struct Map *map, char S1, char S2) { if (map->head[B1].dajoin != NULL) { if (map->head[B1].dajoin->data > B2) { struct Node *temp = malloc(sizeof(struct Node)); temp->data = B2; temp->next = map->head[B1].dajoin; map->head[B1].dajoin = temp; } else { struct Node *demp = map->head[B1].dajoin; struct Node *before = demp; while (demp && B2 > demp->data) { before = demp; demp = demp->next; } struct Node *emp = malloc(sizeof(struct Node)); emp->data = B2; emp->next = before->next; before->next = emp; } } else { map->head[B1].dajoin = malloc(sizeof(struct Node)); map->head[B1].dajoin->data = B2; map->head[B1].dajoin->next = NULL; } } void print(struct Map *map) { int i; for (i = 0; i < map->spot; i++) { char ele = i + 'A'; struct Node *p = map->head[i].dajoin; printf("与%c连接的结点有:", ele); while (p) { char ele = p->data + 'A'; printf("%c ", ele); p = p->next; } printf("\n"); } } int main() { struct Map map; creat_graph(&map); print(&map); return 0; }
- C语言建立有向图的邻接表及其遍历操作
- 数据结构 c语言 有向图和无向图邻接表的建立、插入、和删除操作
- 动态单链表的传统存储方式和10种常见操作-C语言实现
- C语言的文件的操作(二)
- 神奇的C语言,这才是C语言大牛操作,作为面试题,怕是秒杀众人
- C语言文件操作之fgets()
- C语言文件操作函数大全
- C语言之文件操作01——打印1000以内的质数到文件
- 文件操作04 - 零基础入门学习C语言63
- c语言中的位移位操作
- C语言字符串操作常用库函数
- C语言实现栈数据结构操作
- linux下sqlite用c语言回调函数操作数据库
- C语言操作Redis总结
- C语言与数据库操作入门
- C语言对Excel操作
- 第十二周项目2-操作用邻接表存储的图
- 单片机的C语言中位操作用法
- 【C语言提高45】【文件操作API】----- 标准文件的读写
- C语言字符串操作常用库函数