当前位置: 首页 > article >正文

数据结构图的应用-关键路径(有向图+邻接表存储结构+C语言代码)-附带终端输入+图片

数据结构图的应用关键路径代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<stdbool.h>
#define MVNum 100
//图的邻接表
typedef struct ArcNode
{
	int adjvex;//顶点
	int weight;//权值
	struct ArcNode* nextarc;
}ArcNode;
typedef struct VNode
{
	char data;
	ArcNode* firstarc;
}VNode,AdjList[MVNum];
typedef struct
{
	AdjList vertices;//邻接表
	AdjList converse_vertices;//逆邻接表
	int vexnum, arcnum;
}ALGraph;

//顺序栈的结构体
typedef struct
{
	int* base;
	int* top;
	int stacksize;
}spStack;

//全局变量
spStack S;
int indegree[MVNum];//数组indegree存放个顶点的入度
int ve[MVNum];//vi的最早发生时间
int vl[MVNum];//vi的最迟发生时间
int topo[MVNum];//记录拓扑排序的顶点顺序

//栈的初始化
void InitStack(spStack* S)
{
	S->base = (int*)malloc(sizeof(int) * MVNum);
	if (!S->base)
	{
		exit(1);
	}
	S->top = S->base;
	S->stacksize = MVNum;
}
//入栈
void Push(spStack* S, int i)
{
	if (S->top - S->base == S->stacksize)
	{
		return;
	}
	*S->top++ = i;
}
//出栈
void Pop(spStack* S, int* i)
{
	if (S->top == S->base)
	{
		return;
	}
	*i = *--S->top;
}
bool StackEmpty(spStack S)
{
	if (S.top == S.base)
	{
		return true;//为空返回对
	}
	return false;
}
int Locate(ALGraph G,char u)
{
	int i;
	for (i = 0; i < G.vexnum; i++)
	{
		if (G.vertices[i].data == u)
		{
			return i;
		}
	}
	return -1;
}
//创建邻接表
int CreateUDG(ALGraph* G)
{
	int i, k;
	printf("请输入顶点数+边数\n");
	scanf("%d %d", &G->vexnum, &G->arcnum);
	getchar();

	printf("请输入顶点的信息\n");
	for (i = 0; i < G->vexnum; i++)
	{
		printf("请输入第%d个顶点:", i + 1);
		scanf(" %c", &G->vertices[i].data);
		G->converse_vertices[i].data = G->vertices[i].data;
		G->vertices[i].firstarc = NULL;
		G->converse_vertices[i].firstarc = NULL;
	}

	printf("请输入边依附的顶点以及权值\n");
	for (k = 0; k < G->arcnum; k++)
	{
		char v1, v2;
		int i, j, w;
		printf("请输入第%d条边依附的顶点和权值:",k+1);
		scanf(" %c %c %d", &v1, &v2, &w);
		i = Locate(*G, v1);
		j = Locate(*G, v2);
		//邻接表的边表插入(出度)
		ArcNode* p1 = (ArcNode*)malloc(sizeof(ArcNode));
		p1->adjvex = j;
		p1->nextarc = G->vertices[i].firstarc;
		G->vertices[i].firstarc = p1;
		p1->weight = w;
		//逆邻接表的边表插入(入度)
		ArcNode* p2 = (ArcNode*)malloc(sizeof(ArcNode));
		p2->adjvex = i;
		p2->nextarc = G->converse_vertices[j].firstarc;
		G->converse_vertices[j].firstarc = p2;
		p2->weight = w;
	}
	return 1;
}
void FindInDegree(ALGraph G)
{
	int i, count;
	//将入度存储到indegree
	for (i = 0; i < G.vexnum; i++)
	{
		count = 0;
		ArcNode* p = G.converse_vertices[i].firstarc;
		while (p)
		{
			p = p->nextarc;
			count++;
		}
		indegree[i] = count;
	}
}
int TopologicalOrder(ALGraph G, int topo[])
{
	int m;
	//统计入度函数
	FindInDegree(G);
	InitStack(&S);
	//把入度为0的进栈
	for (int i = 0; i < G.vexnum; i++)
	{
		if (indegree[i] == 0)
		{
			Push(&S, i);
		}
	}
	m = 0;//统计顶点数
	while (!StackEmpty(S))
	{
		int i;
		Pop(&S, &i);
		topo[m] = i;
		m++;
		ArcNode* p = G.vertices[i].firstarc;
		while (p)
		{
			int k = p->adjvex;//3 2 1 
			--indegree[k];//顶点被取出,指向它的相邻的顶点的入度-1
			if (indegree[k] == 0)
			{
				Push(&S, k);
			}
			p = p->nextarc;
		}
	}
	if (m<G.vexnum)
	{
		return 0;
	}
	else {
		return 1;
	}
}
int CriticalPath(ALGraph G)
{
	int n, i, k, j, e, l;
	//调用拓扑排序算法,使拓扑序列保存在topo中,若调用失败,则存在有向环,返回ERROR 
	if (!TopologicalOrder(G,topo))
	{
		return 0;
	}
	n = G.vexnum;
	for (i = 0; i < n; i++)
	{
		ve[i] = 0;//最早开始时间数组置为0
	}
	/*――――――――――按拓扑次序求每个事件的最早发生时间-――――-―――――*/
	for (i = 0; i < n; i++)
	{
		k = topo[i];//第一个肯定是0
		ArcNode* p = G.vertices[k].firstarc;
		//从0出发对0-1 0-2 0-3的权值赋值
		while (p)
		{
			j = p->adjvex;//3 2 1
			if (ve[j] < ve[k]+p->weight)//MAX[ve(0)+wij];
			{
				ve[j] = ve[k] + p->weight;//7
			}
			p = p->nextarc;//2 1
		}
	}
	//全部权值置为18
	for (i = 0; i < n; i++)
	{
		vl[i] = ve[n - 1];
	}
	/*――――――――――按逆拓扑次序求每个事件的最迟发生时间-――――-―――――*/
	for (i = n - 1; i >= 0; i--)//8->0
	{
		k = topo[i];//8 7
		ArcNode* p = G.vertices[k].firstarc;
		while (p)//i = 8跳过
		{
			j = p->adjvex;//8
			if (vl[k] > vl[j] - p->weight)
			{
				vl[k] = vl[j] - p->weight;
			}
			p = p->nextarc;
		}
	}
	/*――――――――――――判断每一活动是否为关键活动-――――――-―――――*/
	printf("关键路径为:  ");
	for (i = 0; i < n; i++)
	{
		ArcNode* p = G.vertices[i].firstarc;
		while (p)
		{
			j = p->adjvex;// 3
			e = ve[i];//取出0的最早开始时间
			l = vl[j] - p->weight;//取出当前j的最迟开始时间
			if (e == l)
			{
				printf(" %c --> %c ", G.vertices[i].data, G.vertices[j].data);
			}
			p = p->nextarc;
		}
	}
	return 1;
}
int main()
{
	printf("************算法6.13 关键路径算法**************\n");
	ALGraph G;
	CreateUDG(&G);
	CriticalPath(G);
	return 0;
}

数据结构图的应用关键路径图片如下:

数据结构图的应用关键路径终端输入如下:

 请输入顶点+边数
9 11
请输入顶点的信息
请输入第1个顶点:0
请输入第2个顶点:1
请输入第3个顶点:2
请输入第4个顶点:3
请输入第5个顶点:4
请输入第6个顶点:5
请输入第7个顶点:6
请输入第8个顶点:7
请输入第9个顶点:8
请输入(vi,vj)以及权值
请输入第1条边的顶点和权值:0 1 6
请输入第2条边的顶点和权值:0 2 4
请输入第3条边的顶点和权值:0 3 5
请输入第4条边的顶点和权值:1 4 1
请输入第5条边的顶点和权值:2 4 1
请输入第6条边的顶点和权值:3 5 2
请输入第7条边的顶点和权值:4 6 9
请输入第8条边的顶点和权值:4 7 7
请输入第9条边的顶点和权值:5 7 4
请输入第10条边的顶点和权值:6 8 2
请输入第11条边的顶点和权值:7 8 4
关键路径为: 0 -> 1  1 -> 4  4 -> 7  4 -> 6  6 -> 8  7 -> 8


http://www.kler.cn/news/367892.html

相关文章:

  • 来源爬虫程序调研报告
  • Go 语言基础教程:7.Switch 语句
  • OpenFeign返回参数统一处理
  • 2024 BuildCTF 公开赛|MISC
  • Linux: Shell编程中的应用之基于sh脚本生成网页
  • 论1+2+3+4+... = -1/12 的不同算法
  • jaavascript使用正则表达式校验字符串pwd,是否符合 包含大写小写数字特殊字符长度超过8位
  • 【AI日记】24.10.27
  • Git合并多个分支中的提交内容
  • 基于SSM+微信小程序的跑腿管理系统(跑腿1)
  • Excel技巧:Excel文件批量提取文件名
  • 【Chapter 4】因果推断中的线性回归和正交化
  • 《Redis实战》note-10 扩展Redis
  • 【MySQL】C语言连接MySQL数据库2——基本API的学习
  • 手把手教——class1_VScode配置C++环境
  • 大粤金融智能交易系统的创新与应用
  • FPGA 蜂鸣器 音乐播放器
  • 【Docker命令】日常使用的Docker命令
  • Pandas库学习Day21
  • javaWeb项目-ssm+vue高校网课管理系统功能介绍
  • Cursor零基础小白教程系列 - 创建你的第一个Cursor 项目
  • CSS伪元素以及伪类和CSS特性
  • 获 Sei 基金会投资的 MetaArena :掀起新一轮链上游戏革命
  • Adam优化器算法详解
  • 【C++复习】第二弹-内存管理
  • 3.Linux按键驱动-添加循环队列