特殊“邻接表”建图方法

来源:互联网 发布:程序员接私活 编辑:程序博客网 时间:2024/06/04 18:24

(此文借鉴 dollarzhaole 的 《邻接表建图方法及代码》 )

说明:

        建立有向图(稍加更改可变为无向图);

        第一行输入n 表示边数;

        随后n行输入a, b, c 分别表示边的起点, 终点, 权值;


输入示例:

 5

 3 4 6
 3 7 8
 1 3 6
 2 4 7
 3 5 1


图示例:

              

方法:

        利用数组和结构体模拟边与边的关系, 极大的节省空间和时间;


图示解析:


代码:

1.有向图:

#include <stdio.h>#include <string.h>#define N 100struct Edge{//此结构体表示边int start;//边起点int end;//边终点int weight;//权值int next;//下一个与start有关的边};int first[N];//存储以下标为起点的边的(最后)位置Edge e[N] ;//存储边的具体信息void Build_Graph()//建图{int edges;//边数memset(first, -1, sizeof(first));//-1表示该起点不存在连边scanf("%d", &edges);for(int i = 0; i < edges; i ++){scanf("%d%d%d", &e[i].start, &e[i].end, &e[i].weight);//输入节点信息e[i].next = first[e[i].start];first[e[i].start] = i;/* first数组存储的是"最新的"以下标i为起点的边在e数组中的位置, 所以有新数据都要先修改过first, 类似单链表的头插法;   但在更改first[i]的值前, 应先修改边的next值为first[i]的当前值,犹如单链表头插前要修改 newnode ->next = head ->next;*/}}void Print_Graph(){ for(int i = 1; i < 10; i ++)//输出图 10暂且表示顶点最大值     { if(first[i] == -1) continue;//该起点没边         printf("以%d为起点的所有边的信息:\n", i);          for(int j = first[i]; j != -1; j = e[j].next)//遍历以j为起点的所有边的信息             printf("%d %d %d\n", e[j].start, e[j].end, e[j].weight); printf("\n");     }}int main(){Build_Graph();Print_Graph();return 0;}

2.无向图:

#include <stdio.h>#include <string.h>#define N 100struct Edge{//此结构体表示边int start;//边起点int end;//边终点int weight;//权值int next;//下一个与start有关的边};int first[N];//存储以下标为起点的边的(最后)位置Edge e[N] ;//存储边的具体信息void Build_Graph()//建图{int edges;//边数(关系数)memset(first, -1, sizeof(first));//-1表示该起点不存在连边scanf("%d", &edges);for(int i = 0; i < edges * 2; i ++){scanf("%d%d%d", &e[i].start, &e[i].end, &e[i].weight);//输入节点信息e[i].next = first[e[i].start];first[e[i].start] = i;i ++;//无向图增加代码e[i].start = e[i - 1].end;e[i].end = e[i - 1].start;e[i].weight = e[i - 1].weight;e[i].next = first[e[i].start];first[e[i].start] = i;/* first数组存储的是"最新的"以下标i为起点的边在e数组中的位置, 所以有新数据都要先修改过first, 类似单链表的头插法;   但在更改first[i]的值前, 应先修改边的next值为first[i]的当前值,犹如单链表头插前要修改 newnode ->next = head ->next;*/}}void Print_Graph(){ for(int i = 1; i < 10; i ++)//输出图 10暂且表示顶点最大值     { if(first[i] == -1) continue;//该起点没边         printf("以%d为起点的所有边的信息:\n", i);          for(int j = first[i]; j != -1; j = e[j].next)//遍历以j为起点的所有边的信息             printf("%d %d %d\n", e[j].start, e[j].end, e[j].weight); printf("\n");     }}int main(){Build_Graph();Print_Graph();return 0;}