图的邻接矩阵实现(动态)

图的结构体

 与邻接表不同,用邻接矩阵实现图,需要用一个一维数组存储顶点,一个二维数组存储邻接矩阵

由于此处是动态分配,使用指针

typedef int  ArcType;

//点
struct Vertex {
	char* name;			//	点的名字
};

//弧
struct Arc {
	ArcType ArcValue;
};

//图的类型
enum GraphKind {
	DG,			//0	 有向图
	DN,			//1  有向网
	UDG,		//2  无向图
	UDN			//3  无向网
};

//图
struct Graph {
	int VertexNum, ArcNum;		//点数,弧数
	GraphKind kind;				//图的种类
	Vertex* v;
	Arc** arc;
};

创建图

//获取顶点v的序号(下标)
int VertexLoc(Graph G, Vertex v) {
	for (int i = 0; i < G.VertexNum; i++) {
		if (strcmp(v.name, G.v[i].name) == 0)
			return i;
	}
	return -1;    //否则返回-1
}

//创建图
void CreateGraph(Graph& G) {
	//1.图类型
	//2.输入点数、弧数
	//3.给点起名字
	//4.创建弧的邻接矩阵

	//1.图类型
	cout << "请输入图的类型(0有向图 1有向网 2无向图 3无向网)" << endl;
	int kind;
	cin >> kind;
	G.kind = (GraphKind)kind;

	//2.输入点数、弧数
	cout << "请输入 点数 弧数" << endl;
	cin >> G.VertexNum >> G.ArcNum;
	//给点的数组分配内存
	G.v = (Vertex*)malloc(G.VertexNum * sizeof(Vertex));
	if (!G.v)
		exit(ERROR);

	//3.给点起名字
	for (int i = 0; i < G.VertexNum; i++) {
		cout << "请输入第" << i + 1 << "个点的名字:" << endl;
		G.v[i].name = (char*)malloc(sizeof(char));
		if (!G.v[i].name)
			exit(ERROR);
		cin >> G.v[i].name;
	}

	//4.初始化+创建弧的邻接矩阵
	int value = 0;	 //图
	if (G.kind % 2)  //网
		value = INF;


	G.arc = (Arc**)malloc(G.VertexNum * sizeof(Arc*));	//列
	if (!G.arc)
		exit(ERROR);
	for (int i = 0; i < G.VertexNum; i++) {
		G.arc[i] = (Arc*)malloc(G.VertexNum * sizeof(Arc));
		if (!G.arc[i])
			exit(ERROR);
		for (int j = 0; j < G.VertexNum; j++)
			G.arc[i][j].ArcValue = value;
	}

	Vertex tail, head;
	tail.name = (char*)malloc(sizeof(char));
	head.name = (char*)malloc(sizeof(char));

	//创建
	//图
	if (G.kind % 2 == 0) {
		for (int i = 0; i < G.ArcNum; i++) {
			cout << "请输入第" << i + 1 << "条弧的弧尾 弧头";
			cin >> tail.name >> head.name;
			int tailLoc, headLoc;
			tailLoc = VertexLoc(G, tail);
			headLoc = VertexLoc(G, head);
			G.arc[tailLoc][headLoc].ArcValue = 1;
			//无向图
			if (G.kind == 2)
				G.arc[headLoc][tailLoc].ArcValue = 1;
		}
	}

	//网
	if (G.kind % 2) {
		for (int i = 0; i < G.ArcNum; i++) {
			cout << "请输入第" << i + 1 << "条弧的 弧尾 弧头 权值";
			ArcType value;
			cin >> tail.name >> head.name >> value;
			int tailLoc, headLoc;
			tailLoc = VertexLoc(G, tail);
			headLoc = VertexLoc(G, head);
			G.arc[tailLoc][headLoc].ArcValue = value;

			//无向网
			if (G.kind == 3)
				G.arc[headLoc][tailLoc].ArcValue = value;
		}
	}
}

 *其中VertexNum 行VertexNum 列二维数组的动态分配内存*

G.arc = (Arc**)malloc(G.VertexNum * sizeof(Arc*));

G.arc[i] = (Arc*)malloc(G.VertexNum * sizeof(Arc));

 输出图(遍历二维数组即可)

//输出图
void PrintGraph(Graph& G) {
	//输出顶点
	cout << "该图的" << G.VertexNum << "个顶点为" << endl;
	for (int i = 0; i < G.VertexNum; i++)
		cout << G.v[i].name << " ";

	cout << endl;
	//输出邻接矩阵
	for (int i = 0; i < G.VertexNum; i++) {
		for (int j = 0; j < G.VertexNum; j++) {
			cout << G.arc[i][j].ArcValue << "     ";
		}
		cout << endl;
	}
}

 点和弧的插入删除

1.插入点要给点数组和邻接矩阵重新分配内存和初始化

2. 删除点要删除和它关联的所有弧,并移动下标

//插入点
void InsertVertex(Graph& G, Vertex v) {
	//点+1
	Vertex* new_v = (Vertex*)realloc(G.v, (G.VertexNum + 1) * sizeof(Vertex));
	if (!new_v)
		exit(OVERFLOW);
	new_v[G.VertexNum] = v;
	G.v = new_v;

	//邻接矩阵+1行1列
	Arc** new_arc = (Arc**)realloc(G.arc, (G.VertexNum + 1) * sizeof(Arc*));
	if (!new_arc)
		exit(OVERFLOW);
	for (int i = 0; i < G.VertexNum; i++) {
		new_arc[i] = (Arc*)realloc(G.arc[i], (G.VertexNum + 1) * sizeof(Arc));
		if (!new_arc[i])
			exit(OVERFLOW);
	}
	new_arc[G.VertexNum] = (Arc*)malloc((G.VertexNum + 1) * sizeof(Arc));
	G.arc = new_arc;
	ArcType value = 0;
	if (G.kind % 2)
		value = INF;
	for (int i = 0; i <= G.VertexNum; i++) {
		G.arc[G.VertexNum][i].ArcValue = value;
		G.arc[i][G.VertexNum].ArcValue = value;
	}
	G.VertexNum++;
}

//添加弧
status InsertArc(Graph& G, Vertex tail, Vertex head) {
	int tailLoc, headLoc;

	tailLoc = VertexLoc(G, tail);

	if (tailLoc == -1)
		return ERROR;
	headLoc = VertexLoc(G, head);
	if (headLoc == -1)
		return ERROR;


	int value = 1;

	if (G.arc[tailLoc][headLoc].ArcValue != 0 && G.arc[tailLoc][headLoc].ArcValue != INF)		//该点已存在弧
		return ERROR;

	ArcType ArcValue;
	if (G.kind % 2 == 1) {
		//网
		cout << "请输入该弧的权值" << endl;
		cin >> ArcValue;
	}
	G.arc[tailLoc][headLoc].ArcValue = ArcValue;
	if (G.kind > 2)
		//无向
		G.arc[headLoc][tailLoc].ArcValue = ArcValue;
	G.ArcNum++;
	return OK;
}

//删除弧
status DeleteArc(Graph& G, Vertex tail, Vertex head) {
	int tailLoc = VertexLoc(G, tail);
	int headLoc = VertexLoc(G, head);
	if (tailLoc == -1 || headLoc == -1)
		return ERROR;
	int ArcValue = 0;
	if (G.kind % 2 == 1)	//网
		ArcValue = INF;
	if (G.arc[tailLoc][headLoc].ArcValue == 0 || G.arc[tailLoc][headLoc].ArcValue == INF)		//当前弧不存在
		return ERROR;

	G.arc[tailLoc][headLoc].ArcValue = ArcValue;
	if (G.kind < 2)		//有向
		G.arc[headLoc][tailLoc].ArcValue = ArcValue;
	G.ArcNum--;
	return OK;
}


//删除顶点
status DeleteVertex(Graph& G, Vertex v) {
	int vLoc = VertexLoc(G, v);
	if (vLoc == -1)
		return ERROR;

	//删除相关弧
	for (int i = 0; i < G.VertexNum; i++)
		DeleteArc(G, v, G.v[i]);
	for (int i = 1; i < G.VertexNum; i++)
		DeleteArc(G, G.v[i], v);

	//移动弧下标
	for (int i = vLoc; i < G.VertexNum - 1; i++) {
		G.arc[i] = G.arc[i + 1];
		for (int j = 0; j < G.VertexNum; j++)
			G.arc[j][i] = G.arc[j][i + 1];
	}

	G.VertexNum--;
	return OK;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值