【数据结构/C语言版】【图】邻接矩阵存储

邻接矩阵

利用二维数组的下标,将i映射为出发点,将j映射为目标点,在arr[i][j]中存储权值等信息,如果两点间没有任何关系初始化arr[i][j]为无穷。于是可以将图的关系存入二维数组中。
邻接矩阵存图优势
1、支持有向图无向图
2、支持带边权和不带边权
3、支持自环
4、适合处理稠密图
邻接矩阵存图缺点
1、浪费空间(空间复杂度o(n^2))、不适合处理稀疏图
测试数据:

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

输出结果:

2147483647 2147483647 7 5
2147483647 2147483647 5 6
7 5 2147483647 2147483647
5 6 2147483647 2147483647

代码:

#include<iostream>
#include<climits>
#include<string>
#include<cstdlib> 
using namespace std;
#define ERROR -1

#define MAX_VERTEX_NUM 20 //最多顶点个数 
#define INFINITY INT_MAX //最大值 
typedef enum { DG, DN, UDG, UDN } GraphKind; //有向图、有向网、无向图、无向网
typedef int VRType, Status;
typedef string VertexType;

typedef struct ArcCell {
	VRType adj; //VRType是顶点关系类型。对无权图用0
				//表示相邻否;对带权图则为权值类型
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct {
	VertexType vexs[MAX_VERTEX_NUM]; //顶点向量 
	AdjMatrix arcs; //邻接矩阵 
	int vexnum, arcnum; //图的当前顶点数和弧数 
	int kind;
}MGraph;

//根据映射定位下标 
int LocateVex(MGraph G, VertexType v)
{
	for (int i = 0; i < G.vexnum; i++) {
		if (v == G.vexs[i]) return i;
	}
	return ERROR;
}

Status CreateDG(MGraph& G)//有向图 
{
	cout << "请输入顶点数和弧数:\n";
	cin >> G.vexnum >> G.arcnum;
	for (int i = 0; i < G.vexnum; i++) {
		cout << "请输入向量信息:\n";
		cin >> G.vexs[i];
	}

	for (int i = 0; i < G.vexnum; i++) {
		for (int j = 0; j < G.vexnum; j++) {
			G.arcs[i][j].adj = INFINITY;
		}
	}

	VertexType v, u; // 出发点 目标点 
	for (int k = 0; k < G.arcnum; k++) {
		cout << "请输入第" << k + 1 << "条弧的信息(v,u):\n";
		cin >> v >> u;
		int i = LocateVex(G, v);
		int j = LocateVex(G, u);
		G.arcs[i][j].adj = 1;
	}
	return 1;
}

Status CreateDN(MGraph& G)//有向网 
{
	cout << "请输入顶点数和弧数:\n";
	cin >> G.vexnum >> G.arcnum;
	for (int i = 0; i < G.vexnum; i++) {
		cout << "请输入向量信息:\n";
		cin >> G.vexs[i];
	}

	for (int i = 0; i < G.vexnum; i++) {
		for (int j = 0; j < G.vexnum; j++) {
			G.arcs[i][j].adj = INFINITY;
		}
	}

	VertexType v, u; // 出发点 目标点 
	for (int k = 0; k < G.arcnum; k++) {
		cout << "请输入第" << k + 1 << "条弧的信息(v,u):\n";
		cin >> v >> u;
		int i = LocateVex(G, v);
		int j = LocateVex(G, u);
		cout << "请输入包含的额外信息(边权):\n";
		cin >> G.arcs[i][j].adj;
	}
	return 1;
}

Status CreateUDG(MGraph& G)//无向图 
{
	cout << "请输入顶点数和弧数:\n";
	cin >> G.vexnum >> G.arcnum;
	for (int i = 0; i < G.vexnum; i++) {
		cout << "请输入向量信息:\n";
		cin >> G.vexs[i];
	}

	for (int i = 0; i < G.vexnum; i++) {
		for (int j = 0; j < G.vexnum; j++) {
			G.arcs[i][j].adj = INFINITY;
		}
	}

	VertexType v, u; // 出发点 目标点 
	for (int k = 0; k < G.arcnum; k++) {
		cout << "请输入第" << k + 1 << "条弧的信息(v,u):\n";
		cin >> v >> u;
		int i = LocateVex(G, v);
		int j = LocateVex(G, u);
		G.arcs[i][j].adj = G.arcs[j][i].adj = 1;
	}
	return 1;
}

Status CreateUDN(MGraph& G)//无向网 
{
	cout << "请输入顶点数和弧数:\n";
	cin >> G.vexnum >> G.arcnum;
	for (int i = 0; i < G.vexnum; i++) {
		cout << "请输入第" << i + 1 << "向量信息:\n";
		cin >> G.vexs[i];
	}

	for (int i = 0; i < G.vexnum; i++) {
		for (int j = 0; j < G.vexnum; j++) {
			G.arcs[i][j].adj = INFINITY;
		}
	}

	VertexType v, u; // 出发点 目标点 
	int w; // 权重 
	for (int k = 0; k < G.arcnum; k++) {
		cout << "请输入第" << k + 1 << "条弧的信息(v,u):\n";
		cin >> v >> u;
		int i = LocateVex(G, v);
		int j = LocateVex(G, u);
		cout << "请输入包含的额外信息(边权):\n";
		cin >> G.arcs[i][j].adj;
		G.arcs[j][i].adj = G.arcs[i][j].adj;
	}
	return 1;
}

Status CreateGraph(MGraph& G)
{
	cin >> G.kind;
	switch (G.kind)
	{
	case DG:return CreateDG(G);
	case DN:return CreateDN(G);
	case UDG:return CreateUDG(G);
	case UDN:return CreateUDN(G);
	default: return ERROR;
	}
}//CreateGraph

void TraveGraph(MGraph G)
{
	for (int i = 0; i < G.vexnum; i++) {
		for (int j = 0; j < G.vexnum; j++) {
			cout << G.arcs[i][j].adj << ' ';
		}
		cout << '\n';
	}
}

int main()
{
	MGraph G;
	cout << "请输入要创建的图的类型(有向图 0、有向网 1、无向图 2、无向网 3):\n";
	CreateGraph(G);
	TraveGraph(G);
	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,针对你的问题,我来解答一下。首先,我们需要明确分枝限界法的基本思想:将搜索过程中的所有可能路径,按照某种方式行排序,并将不可能成为最优路径的路径舍弃,从而减少搜索范围,提高效率。 具体操步骤如下: 1. 初始化:设置起点s的路径长度为0,将s插入到优先队列中。 2. 入循环:从优先队列中取出路径长度最小的路径p,检查p的终点是否为目标点t,如果是,则返回路径长度和路径条数;否则,扩展p的所有后继节点,得到新路径,并计算新路径的长度,将新路径插入优先队列中。 3. 对优先队列中的所有路径行排序,保留路径长度最小的前k条路径,舍弃其余路径。 4. 重复2-3步,直到优先队列为空,或者找到目标点t。 下面是具体的实现过程: 1. 定义一个节点类,包括当前节点编号、从起点到该节点的路径长度、从起点到该节点的路径条数、该节点的前驱节点。 2. 定义一个优先队列,用于存储所有可能的路径,按照路径长度行排序。 3. 将起点s插入到优先队列中,设置起点到起点的路径长度为0,起点到起点的路径条数为1。 4. 入循环,从优先队列中取出路径长度最小的路径p,检查p的终点是否为目标点t,如果是,则返回路径长度和路径条数;否则,扩展p的所有后继节点。 5. 对于每个后继节点v,如果v未被访问过,则计算从起点到v的路径长度和路径条数,并将v插入到优先队列中。 6. 对优先队列中的所有路径行排序,保留路径长度最小的前k条路径,舍弃其余路径。 7. 重复4-6步,直到优先队列为空,或者找到目标点t。 最后,得到的最短路径长度和路径条数即为所求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_zhizi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值