数据结构 | 第七章 图

一、图

1、图的定义

定义

由顶点的有穷非空集合和顶点之间边的集合组成,用(V, E)表示。V为顶点,E为边

注意

  • 图中的数据元素为顶点;
  • 图中顶点不存在空,边可以为空;
1.1 各种图的定义
  • 无向边:若顶点vi到vj之间的边没有方向。用无序偶对(vi, vj)来表示;
  • 无向图: 图中任意俩个顶点之间的边都是无向边
  • 有向边(弧):若顶点vi到vj之间的边有方向。用有序偶对<vi, vj>来表示。vi为弧尾,vj为弧头;
  • 有向图:任意俩个顶点之间的边都是有向边
  • 简单图:若不存在顶点到其自身的边,且同一条边不重复出现
  • 无向完全图:在无向图中,若任意俩个顶点之间都存在边;
  • 有向完全图:在有向图中,若任意俩个顶点之间都存在方向互为相反的俩条弧
  • 稠密图:有很少条边或弧的图;
  • :与图的边或弧相关的树;
  • :带的图;
  • 子图:若有俩图G=(V,{E})G1=(V1, {E1}),若V1属于VE1属于E,则G1为G的子图。
1.2 图的顶点与边间关系
  • 邻接点:对无(有)向图G=(V, {E}),若边(V, V1)属于E,则V和V1互为邻接点
  • :顶点V的度是和V相关联的边的数目,TD(V);
  • 入度:v,v1,以v为头的弧的数目,ID(v);
  • 出度:v,v1,以v为尾的弧OD(v);
  • 顶点v的度:TD(v)=ID(v)+OD(v);
  • 图的路径:路径上的边或弧的数目;
  • 回路或环:第一个顶点到最后一个顶点相同的路径;
  • 简单路径:顶点不重复出现的路径;
  • 简单回路:除第一个顶点和最后一个之外,其余顶点不重复出现的回路。
1.3 连通图相关术语
  • 连通图:无向图G,从v到v1有路径;
  • 连通分量:无向图中的极大连通子图
    • 子图且连通,含极大顶点数,具有极大顶点数的连通子图包含依附于这些顶点的所有边;
  • 极大连通图(强连通图):有向图中,若对于每一对(v,v1)属于V,且v!=v1,从v1到v和从v到v1都存在路径;
  • 生成树:是一个极小连通图,它含图中全部的n个顶点,构成n-1条边
  • 若一个图有n个顶点和小于n-1条边,则是非连通图,若多余n-1条,则必定构成
  • 判断有向树:若有向图恰有一个顶点的入度为0,其余顶点的入度均为1;
2、图的存储结构
2.1 邻接矩阵
  • 顶点不分主次、大小则考虑用一维数组;边或弧由于是顶点与顶点之间的关系则考虑二维数组
  • 无向图的边数组是一个对称矩阵
  • 顶点度就是第i行或列的元素之和。(行出度,列入度);
  • 有向图的矩阵不对称
  • 时间复杂度:n个顶点和e条边的无向网图的时间复杂度度为O(n+n^2^+e)
2.2 邻接表
  • 数组与链表相结合的存储方法;
    • 每个数据元素需要存储指向第一个邻接点的指针,以便查找该顶点的边信息;
    • 无向图称为顶点v1的边表,有向图则为v1弧尾的出边表;
  • 若要判断vi到vj是否存在边,则只需要测试顶点vi的边表中是否存在结点vk的下标j;
  • 时间复杂度:对于n个顶点,e条边,O(n+e)
2.3 十字链表
  • 将邻接表和逆邻接表整合一起;以求得出度、入度;
  • 顶点表data:数据域、firstin:入边表头指针,firstout:出边表头指针;
  • 边表tailvex:弧起点在顶点表的下标;headvex:弧终点在顶点表中的下标;headlink:入边表指针域,指向终点相同的下一条边;taillink:指边表指针域,指向起点相同的下一条边。
2.4 邻接多重表
  • 边表ivex和jvex是与某条边依附的俩个顶点在顶点表中下标。ilink指向依附项点ivex的下一条边,jlink指向依附顶点jvex的下一条边;
  • 顶点表data:存储顶点;firstedge指向一条边,顶点下标要与ivex的值相同。注意ilink指向的结点jvex要和它本身的ivex的值相同;
2.5 边集数组

由俩个一维数组,一个是存储顶点的信息,一个是存储边的信息;每个数据元素由一条边的起点下标终点下标组成。

3、图的遍历

遍历:图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次;

遍历的点需要加上标记,避免多次访问

3.1 深度优先遍历(DFS)
  • 在没有碰到重复顶点的情况下,始终向右边走
  • 从图中某一个顶点v出发,访问此顶点,从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到;若图中有顶点尚未被访问,则另选图中一个未曾被访问的点为起点。
  • 不同的存储结构的DFS效率不同:
    • 对于邻接矩阵来说:要查找每个顶点的邻接点需要访问矩阵中的所有元素,要O(n^2^)
    • 对于邻接表来说,取决于顶点和边的数量,要O(n+e)
3.2 广度优先遍历(BFS)

时间复杂度和DFS是一样的

3.3 最小生成树

构造连通网的最小代价生成树。经典算法:普里姆、克鲁斯卡尔

  • 连接全部的点;
  • 不能形成环;
  • 权值之和最小。
3.3.1 普里姆算法(Prim)
  • 先取任意一点;
  • 选择权值最小的边;
  • 选后将顶点看成整体在连接。
3.3.2 克鲁斯卡尔算法(Kruskal)
  • 将所有边和权值列出;
  • 小到大连,若形成环则选下一条边
  • 边等于顶点数-1时结束。
4、最短路径
  • 倆顶点之间经过的边上权值之和最少的路径;第一个为源点,第二个为终点
4.1 迪杰斯特拉算法(Dijkstra)

一步一步求出顶点之间的权值。

4.2 弗洛伊德算法(Floyd)
  • 先初始化D代表顶点到顶点的最短路径权值和的矩阵;P对应顶点的最小路径的前驱矩阵。
  • 适用于所有顶点至所有顶点的最短路径的问题;
5、拓扑排序【无环图的应用】

AOV网:表示工程的有向图中,用顶点表示活动,用表示活动之间的优先关系

在这里插入图片描述

  • 满足从顶点vi到vj有一条路径,则顶点序列中顶点vi必在顶点vj之前;
  • 就是对一个有向图构造拓扑序列的过程;
5.1 拓扑排序算法
  • 从AOV网选择一个入度为0的顶点输出,在删去此顶点,并删取以此顶点为尾的弧,继续执行该步骤,直到输出全部顶点或AOV网不存在入度为0的顶点为止;
  • 使用邻接表会更方便;
  • 使用栈来辅助存储入度为0的顶点,为了避免每个查找时都要取遍历顶点表找有没有入度为0的顶点;
6、关键路径

AOE网:表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间。

在这里插入图片描述
路径长度: 把路径上各个活动持续的时间之和;
关键路径:从源点到汇点具有最大长度;
关键活动:在关键路径上的活动。

6.1 关键路径算法原理
  • 只需找到所有活动的最早开始时间和最晚开始时间,若相等则为关键活动,活动间的活动为关键路径,若不等则不是。
  • 需要以下几个参数:
    • 时间的最早发生时间etv:顶点vk的最早发生时间;
    • 时间的最晚发生时间ltv:顶点vk的最晚发生时间,每个顶点对应的时间最晚需要开始的时间,超出此时间将会延误整个工期。
    • 活动的最早开工时间ete:弧ak的最早发生时间;
    • 活动的最晚开工时间lte:弧ak的最晚发生时间,不推迟工期的最晚开工时间;
  • 有参数前面俩点可以求得后俩点,当ete[k]是否等于lte[k]来判断ak是否时关键活动
6.2 关键路径算法

求etv:即从头到尾找拓扑序列的过程,因此,求关键路径前,需要先调用一次拓扑序列来计算etv和拓扑序列

7、代码实现
7.1 邻接矩阵

GraphModel.h

#include<stdio.h>
#include<string.h>
#include<stdlib.h>



#define OK 1
#define ERROR 0
#define MAX_VerTex 100


#ifdef __cplusplus
extern"C"{
#endif
	/*
	typedef enum{
		DG,		// 有向图
		UDG,	// 无向图
		DN,		// 有向网
		UDN,	// 无向网
	}GrapgKind;
	*/

	/*@ 设置顶点的数据类型为字符串,需要分配空间 */ 
	typedef char * VerTexType;

	/*@ 设置权值类型为整型 */
	typedef int ArcType;

	/*@ 返回的状态 */
	typedef int Status;

#ifdef __cplusplus
}
#endif

MatrixGraph.h

#include "GraphModel.h"

#ifdef __cplusplus
extern"C"{
#endif

	/*@ 图的邻接矩阵 */
	typedef struct{
		VerTexType verTexs[MAX_VerTex];	// 顶点数组
		ArcType arcs[MAX_VerTex][MAX_VerTex];	// 邻接矩阵
		int verTexCount;	// 图的顶点数
		int arcCount;	// 图的边数
		//GrapgKind type;	// 图的类型
	}MatrixGraph;


	/*@ 使用邻接矩阵表示创建无向图 */
	Status CreateUDG(MatrixGraph *G);

	/*@ 使用邻接矩阵表示创建有向图 */
	Status CreateDG(MatrixGraph *G);

	/*@ 使用邻接矩阵表示创建有向网 */
	Status CreateDN(MatrixGraph *G);

	/*@ 获取顶点返回的位置 */
	int GetLocateVex(MatrixGraph *G, VerTexType vex);

	/*@ 测试无向图 */
	void TestUDG();

#ifdef __cplusplus
}
#endif

MatriGraph

#define _CRT_SECURE_NO_DEPRECATE
#include "GraphModel.h"
#include "MatrixGraph.h"

/*@ 使用邻接矩阵表示创建无向图 */
/*
* 无向图特点:
*	其邻接矩阵是对称的;
*	顶点i的度是第i行(列)的个数
*/
Status CreateUDG(MatrixGraph *G){
	int i, j;
	printf("开始构建有向图\n");
	//G->type = UDG;
	printf("请输入顶点数:");
	scanf("%d", &G->verTexCount);
	printf("请输入边数:");
	scanf("%d", &G->arcCount);

	// 输入顶点
	for (i = 0; i < G->verTexCount; ++i){
		printf("顶点%d:", i+1);
		G->verTexs[i] = (VerTexType)malloc(sizeof(char)* 10);
		scanf("%s", G->verTexs[i]);
	}
	// 初始化邻接矩阵为0
	for (i = 0; i < G->verTexCount; ++i){
		for (j = 0; j < G->verTexCount; ++j){
			G->arcs[i][j] = 0;
		}
	}

	printf("请输入邻接点构建邻接矩阵\n");
	for (i = 0; i < G->arcCount; ++i){
		VerTexType vex1 = (VerTexType)malloc(sizeof(char)* 10);
		VerTexType vex2 = (VerTexType)malloc(sizeof(char)* 10);
		printf("顶点:");
		scanf("%s", vex1);
		printf("邻接点:");
		scanf("%s", vex2);
		int x = GetLocateVex(G, vex1);
		int y = GetLocateVex(G, vex2);

		if (x == -1 || y == -1){
			
			return ERROR;
		}
		G->arcs[x][y] = 1;
		G->arcs[y][x] = 1;


		free(vex1);
		free(vex2);
	}

	return OK;
}

/*@ 使用邻接矩阵表示创建有向图 */
/*
*	特点:
*		邻接矩阵可能不对称;
*		顶点的出度=第i行元素之和
*		顶点的入度=第i列元素之和
*		顶点度 = 行+列
*/
Status CreateDG(MatrixGraph *G){
	int i, j;
	printf("开始构建有向图\n");
	//G->type = UDG;
	printf("请输入顶点数:");
	scanf("%d", &G->verTexCount);
	printf("请输入边数:");
	scanf("%d", &G->arcCount);

	// 输入顶点
	for (i = 0; i < G->verTexCount; ++i){
		printf("顶点%d:", i + 1);
		G->verTexs[i] = (VerTexType)malloc(sizeof(char)* 10);
		scanf("%s", G->verTexs[i]);
	}
	// 初始化邻接矩阵为0
	for (i = 0; i < G->verTexCount; ++i){
		for (j = 0; j < G->verTexCount; ++j){
			G->arcs[i][j] = 0;
		}
	}

	printf("请输入邻接点构建邻接矩阵\n");
	for (i = 0; i < G->arcCount; ++i){
		VerTexType vex1 = (VerTexType)malloc(sizeof(char)* 10);
		VerTexType vex2 = (VerTexType)malloc(sizeof(char)* 10);
		printf("顶点:");
		scanf("%s", vex1);
		printf("邻接点:");
		scanf("%s", vex2);
		int x = GetLocateVex(G, vex1);
		int y = GetLocateVex(G, vex2);

		if (x == -1 || y == -1){

			return ERROR;
		}
		G->arcs[x][y] = 1;

		free(vex1);
		free(vex2);
	}

	return OK;
}


/*@ 使用邻接矩阵表示创建有向网 */
Status CreateDN(MatrixGraph *G){
	int i, j;
	printf("开始构建有向网\n");
	//G->type = UDG;
	printf("请输入顶点数:");
	scanf("%d", &G->verTexCount);
	printf("请输入边数:");
	scanf("%d", &G->arcCount);

	// 输入顶点
	for (i = 0; i < G->verTexCount; ++i){
		printf("顶点%d:", i + 1);
		G->verTexs[i] = (VerTexType)malloc(sizeof(char)* 10);
		scanf("%s", G->verTexs[i]);
	}
	// 初始化邻接矩阵为0
	for (i = 0; i < G->verTexCount; ++i){
		for (j = 0; j < G->verTexCount; ++j){
			G->arcs[i][j] = INT_MAX;
		}
	}

	printf("请输入邻接点构建邻接矩阵\n");
	for (i = 0; i < G->arcCount; ++i){
		VerTexType vex1 = (VerTexType)malloc(sizeof(char)* 10);
		VerTexType vex2 = (VerTexType)malloc(sizeof(char)* 10);
		printf("顶点:");
		scanf("%s", vex1);
		printf("邻接点:");
		scanf("%s", vex2);
		int x = GetLocateVex(G, vex1);
		int y = GetLocateVex(G, vex2);

		if (x == -1 || y == -1){

			return ERROR;
		}
		printf("请输入权值:");
		scanf("%d", &G->arcs[x][y]);

		free(vex1);
		free(vex2);
	}

	return OK;
}


/*@ 获取顶点返回的位置 */
int GetLocateVex(MatrixGraph *G, VerTexType vex){
	for (int i = 0; i < G->verTexCount; ++i){
		if (strcmp(G->verTexs[i], vex) == 0){
			return i;
		}
	}
	return -1;
}

/*@ 测试无向图 */
void TestUDG(){
	int i, j;
	MatrixGraph G;
	Status status =  CreateUDG(&G);
	if (status == ERROR){
		return;
	}
	printf("打印无向图邻接矩阵:\n");
	printf("\t");

	for (i = 0; i < G.verTexCount; ++i){
		printf("\t%s", G.verTexs[i]);
	}
	printf("\n");
	for (i = 0; i < G.verTexCount; ++i){
		printf("\t%s", G.verTexs[i]);
		for (j = 0; j < G.verTexCount; ++j){
			printf("\t%d", G.arcs[i][j]);
		}
		printf("\n");
	}

}
7.2 邻接表表示法

AdjListGraph.h

#define _CRT_SECURE_NO_DEPRECATE
#include "GraphModel.h"
#include "MatrixGraph.h"

/*@ 使用邻接矩阵表示创建无向图 */
/*
* 无向图特点:
*	其邻接矩阵是对称的;
*	顶点i的度是第i行(列)的个数
*/
Status CreateUDG(MatrixGraph *G){
	int i, j;
	printf("开始构建有向图\n");
	//G->type = UDG;
	printf("请输入顶点数:");
	scanf("%d", &G->verTexCount);
	printf("请输入边数:");
	scanf("%d", &G->arcCount);

	// 输入顶点
	for (i = 0; i < G->verTexCount; ++i){
		printf("顶点%d:", i+1);
		G->verTexs[i] = (VerTexType)malloc(sizeof(char)* 10);
		scanf("%s", G->verTexs[i]);
	}
	// 初始化邻接矩阵为0
	for (i = 0; i < G->verTexCount; ++i){
		for (j = 0; j < G->verTexCount; ++j){
			G->arcs[i][j] = 0;
		}
	}

	printf("请输入邻接点构建邻接矩阵\n");
	for (i = 0; i < G->arcCount; ++i){
		VerTexType vex1 = (VerTexType)malloc(sizeof(char)* 10);
		VerTexType vex2 = (VerTexType)malloc(sizeof(char)* 10);
		printf("顶点:");
		scanf("%s", vex1);
		printf("邻接点:");
		scanf("%s", vex2);
		int x = GetLocateVex(G, vex1);
		int y = GetLocateVex(G, vex2);

		if (x == -1 || y == -1){
			
			return ERROR;
		}
		G->arcs[x][y] = 1;
		G->arcs[y][x] = 1;


		free(vex1);
		free(vex2);
	}

	return OK;
}

/*@ 使用邻接矩阵表示创建有向图 */
/*
*	特点:
*		邻接矩阵可能不对称;
*		顶点的出度=第i行元素之和
*		顶点的入度=第i列元素之和
*		顶点度 = 行+列
*/
Status CreateDG(MatrixGraph *G){
	int i, j;
	printf("开始构建有向图\n");
	//G->type = UDG;
	printf("请输入顶点数:");
	scanf("%d", &G->verTexCount);
	printf("请输入边数:");
	scanf("%d", &G->arcCount);

	// 输入顶点
	for (i = 0; i < G->verTexCount; ++i){
		printf("顶点%d:", i + 1);
		G->verTexs[i] = (VerTexType)malloc(sizeof(char)* 10);
		scanf("%s", G->verTexs[i]);
	}
	// 初始化邻接矩阵为0
	for (i = 0; i < G->verTexCount; ++i){
		for (j = 0; j < G->verTexCount; ++j){
			G->arcs[i][j] = 0;
		}
	}

	printf("请输入邻接点构建邻接矩阵\n");
	for (i = 0; i < G->arcCount; ++i){
		VerTexType vex1 = (VerTexType)malloc(sizeof(char)* 10);
		VerTexType vex2 = (VerTexType)malloc(sizeof(char)* 10);
		printf("顶点:");
		scanf("%s", vex1);
		printf("邻接点:");
		scanf("%s", vex2);
		int x = GetLocateVex(G, vex1);
		int y = GetLocateVex(G, vex2);

		if (x == -1 || y == -1){

			return ERROR;
		}
		G->arcs[x][y] = 1;

		free(vex1);
		free(vex2);
	}

	return OK;
}


/*@ 使用邻接矩阵表示创建有向网 */
Status CreateDN(MatrixGraph *G){
	int i, j;
	printf("开始构建有向网\n");
	//G->type = UDG;
	printf("请输入顶点数:");
	scanf("%d", &G->verTexCount);
	printf("请输入边数:");
	scanf("%d", &G->arcCount);

	// 输入顶点
	for (i = 0; i < G->verTexCount; ++i){
		printf("顶点%d:", i + 1);
		G->verTexs[i] = (VerTexType)malloc(sizeof(char)* 10);
		scanf("%s", G->verTexs[i]);
	}
	// 初始化邻接矩阵为0
	for (i = 0; i < G->verTexCount; ++i){
		for (j = 0; j < G->verTexCount; ++j){
			G->arcs[i][j] = INT_MAX;
		}
	}

	printf("请输入邻接点构建邻接矩阵\n");
	for (i = 0; i < G->arcCount; ++i){
		VerTexType vex1 = (VerTexType)malloc(sizeof(char)* 10);
		VerTexType vex2 = (VerTexType)malloc(sizeof(char)* 10);
		printf("顶点:");
		scanf("%s", vex1);
		printf("邻接点:");
		scanf("%s", vex2);
		int x = GetLocateVex(G, vex1);
		int y = GetLocateVex(G, vex2);

		if (x == -1 || y == -1){

			return ERROR;
		}
		printf("请输入权值:");
		scanf("%d", &G->arcs[x][y]);

		free(vex1);
		free(vex2);
	}

	return OK;
}


/*@ 获取顶点返回的位置 */
int GetLocateVex(MatrixGraph *G, VerTexType vex){
	for (int i = 0; i < G->verTexCount; ++i){
		if (strcmp(G->verTexs[i], vex) == 0){
			return i;
		}
	}
	return -1;
}

/*@ 测试无向图 */
void TestUDG(){
	int i, j;
	MatrixGraph G;
	Status status =  CreateUDG(&G);
	if (status == ERROR){
		return;
	}
	printf("打印无向图邻接矩阵:\n");
	printf("\t");

	for (i = 0; i < G.verTexCount; ++i){
		printf("\t%s", G.verTexs[i]);
	}
	printf("\n");
	for (i = 0; i < G.verTexCount; ++i){
		printf("\t%s", G.verTexs[i]);
		for (j = 0; j < G.verTexCount; ++j){
			printf("\t%d", G.arcs[i][j]);
		}
		printf("\n");
	}

}

AdjListGraph.h

#define _CRT_SECURE_NO_DEPRECATE
#include "AdjListGraph.h"

/*@ 邻接表表示法创建无向图 */
Status CreateUDG_AdjList(AdjListGraph * G){
	int i;
	printf("下面开始创建无向图....\n");
	printf("请输入顶点数:");
	scanf("%d", &G->vexCount);
	printf("请输入边数:");
	scanf("%d", &G->edgeCount);

	for (i = 0; i < G->vexCount; ++i){
		G->vexes[i].vex = (VerTexType)malloc(sizeof(char)* 10);
		printf("请输入顶点%d:", i + 1);
		scanf("%s", G->vexes[i].vex);
		G->vexes[i].firstEdge = NULL;
	}

	printf("下面请输入顶点和邻接点\n");
	for (i = 0; i < G->vexCount; ++i){
		VerTexType vex1 = (VerTexType)malloc(sizeof(char)* 10);
		VerTexType vex2 = (VerTexType)malloc(sizeof(char)* 10);
		printf("输入顶点:");
		scanf("%s", vex1);	
		printf("输入邻接点:");
		scanf("%s", vex2);
		// 返回顶点的下标
		int x = getLocation_AdjList(G, vex1);
		int y = getLocation_AdjList(G, vex2);
		if (x == -1 || y == -1){
			return ERROR;
		}
		EdgeNode * tempXEdge = (EdgeNode *)malloc(sizeof(EdgeNode));
		tempXEdge->adjVex = x;	// 该边指向这条邻接点的下标
		tempXEdge->nextEdge = G->vexes[y].firstEdge;	// 指向下一条边结点的指针
		tempXEdge->weight = 0;
		G->vexes[y].firstEdge = tempXEdge;

		EdgeNode * tempYEdge = (EdgeNode *)malloc(sizeof(EdgeNode));
		tempYEdge->adjVex = y;	// 该边指向这条邻接点的下标
		tempYEdge->nextEdge = G->vexes[x].firstEdge;	// 指向下一条边结点的指针
		tempYEdge->weight = 0;
		G->vexes[x].firstEdge = tempYEdge;
	}

	return OK;
}

/*@ 邻接表表示法创建有向图 */
Status CreateDG_AdjList(AdjListGraph * G){
	int i;
	printf("下面开始创建有向图....\n");
	printf("请输入顶点数:");
	scanf("%d", &G->vexCount);
	printf("请输入边数:");
	scanf("%d", &G->edgeCount);

	for (i = 0; i < G->vexCount; ++i){
		G->vexes[i].vex = (VerTexType)malloc(sizeof(char)* 10);
		printf("请输入顶点%d:", i + 1);
		scanf("%s", G->vexes[i].vex);
		G->vexes[i].firstArc = NULL;
		G->vexes[i].firstEdge = NULL;
	}

	printf("下面请输入顶点和邻接点\n");
	for (i = 0; i < G->vexCount; ++i){
		VerTexType vex1 = (VerTexType)malloc(sizeof(char)* 10);
		VerTexType vex2 = (VerTexType)malloc(sizeof(char)* 10);
		printf("输入顶点:");
		scanf("%s", vex1);
		printf("输入邻接点:");
		scanf("%s", vex2);
		// 返回顶点的下标
		int x = getLocation_AdjList(G, vex1);
		int y = getLocation_AdjList(G, vex2);
		if (x == -1 || y == -1){
			return ERROR;
		}
		// 出边
		ArcNode * tempYArc = (ArcNode *)malloc(sizeof(ArcNode));
		tempYArc->adjVex = y;	// 该边指向这条邻接点的下标
		tempYArc->nextArc = G->vexes[x].firstArc;	// 指向下一条边结点的指针
		tempYArc->weight = 0;
		G->vexes[x].firstArc = tempYArc;

		// 入边
		EdgeNode * tempXEdge = (EdgeNode *)malloc(sizeof(EdgeNode));
		tempXEdge->adjVex = x;	// 该边指向这条邻接点的下标
		tempXEdge->nextEdge = G->vexes[y].firstEdge;	// 指向下一条边结点的指针
		tempXEdge->weight = 0;
		G->vexes[y].firstEdge = tempXEdge;
	}

	return OK;
}

/*@ 邻接表表示法创建有向图 */
Status CreateDN_AdjList(AdjListGraph * G){
	int i;
	printf("下面开始创建有向图....\n");
	printf("请输入顶点数:");
	scanf("%d", &G->vexCount);
	printf("请输入边数:");
	scanf("%d", &G->edgeCount);

	for (i = 0; i < G->vexCount; ++i){
		G->vexes[i].vex = (VerTexType)malloc(sizeof(char)* 10);
		printf("请输入顶点%d:", i + 1);
		scanf("%s", G->vexes[i].vex);
		G->vexes[i].firstArc = NULL;
		G->vexes[i].firstEdge = NULL;
	}

	printf("下面请输入顶点和邻接点\n");
	for (i = 0; i < G->vexCount; ++i){
		VerTexType vex1 = (VerTexType)malloc(sizeof(char)* 10);
		VerTexType vex2 = (VerTexType)malloc(sizeof(char)* 10);
		printf("输入顶点:");
		scanf("%s", vex1);
		printf("输入邻接点:");
		scanf("%s", vex2);
		// 返回顶点的下标
		int x = getLocation_AdjList(G, vex1);
		int y = getLocation_AdjList(G, vex2);
		if (x == -1 || y == -1){
			return ERROR;
		}
		int weight = 0;
		printf("请输入权值:");
		scanf("%d", &weight);
		// 出边
		ArcNode * tempYArc = (ArcNode *)malloc(sizeof(ArcNode));
		tempYArc->adjVex = y;	// 该边指向这条邻接点的下标
		tempYArc->nextArc = G->vexes[x].firstArc;	// 指向下一条边结点的指针
		tempYArc->weight = weight;
		G->vexes[x].firstArc = tempYArc;

		// 入边
		EdgeNode * tempXEdge = (EdgeNode *)malloc(sizeof(EdgeNode));
		tempXEdge->adjVex = x;	// 该边指向这条邻接点的下标
		tempXEdge->nextEdge = G->vexes[y].firstEdge;	// 指向下一条边结点的指针
		tempXEdge->weight = weight;
		G->vexes[y].firstEdge = tempXEdge;
	}

	return OK;
}

/*@ 获取顶点在数组中的下标 */
int getLocation_AdjList(AdjListGraph * G, VerTexType vex){
	int i;
	for (i = 0; i < G->vexCount; ++i){
		if (strcmp(vex, G->vexes[i].vex) == 0){
			return i;
		}
	}
	return -1;
}

/*@ 测试无向图函数 */
void TestUGD_AdjList(){
	int i;
	AdjListGraph G;
	Status status = CreateUDG_AdjList(&G);
	printf("邻接表表示法为:\n");
	for (i = 0; i < G.vexCount; ++i){
		printf("顶点:%s", G.vexes[i].vex);
		EdgeNode * node = G.vexes[i].firstEdge;
		while (node){
			printf(" -> %d", node->adjVex);
			node = node->nextEdge;
		}
		printf("\n");
	}
}

/*@ 测试有向图函数 */
void TestGD_AdjList(){
	int i;
	AdjListGraph G;
	Status status = CreateDG_AdjList(&G);
	printf("邻接表表示法为:\n");
	for (i = 0; i < G.vexCount; ++i){
		printf("顶点:%s", G.vexes[i].vex);
		EdgeNode * node = G.vexes[i].firstArc;
		while (node){
			printf(" -> %d", node->adjVex);
			node = node->nextArc;
		}
		printf("\n");
	}

	printf("逆邻接表表示法为:\n");
	for (i = 0; i < G.vexCount; ++i){
		printf("顶点:%s", G.vexes[i].vex);
		EdgeNode * node = G.vexes[i].firstEdge;
		while (node){
			printf(" <- %d", node->adjVex);
			node = node->nextEdge;
		}
		printf("\n");
	}
}

/*@ 测试有向图函数 */
void TestGN_AdjList(){
	int i;
	AdjListGraph G;
	Status status = CreateDG_AdjList(&G);
	printf("邻接表表示法为:\n");
	for (i = 0; i < G.vexCount; ++i){
		printf("顶点:%s", G.vexes[i].vex);
		EdgeNode * node = G.vexes[i].firstArc;
		while (node){
			printf(" -> %d(%d)", node->adjVex, node->weight);
			node = node->nextArc;
		}
		printf("\n");
	}

	printf("逆邻接表表示法为:\n");
	for (i = 0; i < G.vexCount; ++i){
		printf("顶点:%s", G.vexes[i].vex);
		EdgeNode * node = G.vexes[i].firstEdge;
		while (node){
			printf(" <- %d(%d)", node->adjVex, node->weight);
			node = node->nextEdge;
		}
		printf("\n");
	}
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jxiepc

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

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

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

打赏作者

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

抵扣说明:

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

余额充值