特殊“邻接表”建图方法

(此文借鉴 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 100

struct 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 100

struct 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值