寻找关键路径(C语言)

要求:计算图中的关键路径(输入输出均使用文件的形式来实现)

测验工程图的样例

 1.开始的准备工作如下

#include<stdio.h>
#include<stdlib.h>
typedef struct Edgelink {		//边链表
	int End;
	int value;
	struct Edgelink *next;
} Edge,*Elink;

typedef struct Vertexlink {		//顶点数组
	int Begin;
	int indegree;
	int Earliest;
	int Lastest;
	Elink next;
} Vertex[100];

typedef struct Graph {
	int Vnum;                   //顶点数目
	int Enum;
	Vertex List;
} Graph;

typedef struct SNode *stack;
struct SNode {
	int Data;
	struct SNode *next;
};

int ve[100];
int vl[100];

2.用邻接表来存储项目图

void CreateLink(Graph *T) {								//图的创建
	int temp;
	int i,j=1;
	FILE *fp;
	fp=fopen("007.txt","r");
	fscanf(fp,"%d",&T->Vnum);
	fscanf(fp,"%d",&T->Enum);
	for(i=1; i<=T->Enum; i++) {
		fscanf(fp,"%d",&temp);
		if(i==1||temp!=T->List[j-1].Begin) {
			T->List[j].Begin=temp;
			T->List[j].indegree=0;
			T->List[j].next=NULL;
			j++;
		}
		Elink p,q;
		p=(Edge*)malloc(sizeof(Edge));
		fscanf(fp,"%d",&(p->End));
		fscanf(fp,"%d",&(p->value));
		p->next=NULL;
		if(T->List[j-1].next==NULL)
			T->List[j-1].next=p;
		else {
			q = T->List[j-1].next;
			while(q->next) {
				q=q->next;
			}
			q->next=p;
		}
	}
	T->List[j].Begin=T->Vnum;
	T->List[j].indegree=0;
	T->List[j].next=NULL;
	fclose(fp);
}

3.计算每个节点的入度

void Indegree(Graph *T) {
	Elink p;
	int i=1,j,k;
	k=T->Vnum;
	int indegree[10]= {0};
	for(j=1; j<k; j++) {
		p=T->List[j].next;
		do {
			for(i=1; i<=k; i++) {
				if(i==p->End) {
					indegree[i]++;
				}
			}
			p=p->next;
		} while(p!=NULL);
	}
	for(i=1; i<=k; i++) {
		T->List[i].indegree=indegree[i];
		//printf("%d",indegree[i]);
	}
}

4.链式栈结构的基本书写准备

stack CreateStack() {
	stack S;
	S=(stack)malloc(sizeof(struct SNode));
	S->next=NULL;
	return S;
}

int IsEmpty(stack S) {
	return (S->next==NULL);
}

void Push(stack S,int item) {
	struct SNode *Tmpcell;
	Tmpcell=(struct SNode*)malloc(sizeof(struct SNode));
	Tmpcell->Data=item;
	Tmpcell->next=S->next;
	S->next=Tmpcell;
}

int Pop(stack S) {
	struct SNode *FirstCell;
	int TopElem;
	if(IsEmpty(S)) {
		printf("堆栈空");
		return ;
	} else {
		FirstCell=S->next;
		S->next=FirstCell->next;
		TopElem=FirstCell->Data;
		free(FirstCell);
		return TopElem;
	}
}

5.用栈结构来实现拓扑排序和逆拓扑排序(为求关键路径做准备)

stack TopOrder(Graph *T) {
	int i,j,k,count=0;
	stack S,Q;
	S=CreateStack();
	Q=CreateStack();
	Elink p;
	for(i=1; i<T->Vnum; i++) {
		if(T->List[i].indegree==0) {
			Push(S,i);
		}
	}
	for(i=1; i<=T->Vnum; i++) {
		ve[i]=0;
	}
	while(!IsEmpty(S)) {
		j=Pop(S);
		Push(Q,j);
		++count;
		for(p=T->List[j].next; p; p=p->next) {
			k=p->End;
			if(--T->List[k].indegree==0)
				Push(S,k);
			if(ve[j]+p->value>ve[k])
				ve[k]=ve[j]+p->value;
		}
	}
	if(count<T->Vnum)
		return 0;
	else
		return Q;
}

6.关键路径的求解函数

void CriticalPath(Graph *T) {
	int a,j,k,el,ee,dut;
	char tag;
	Elink p;
	stack Q;
	Q=TopOrder(T);
	vl[1]=0;
	for(a=2; a<=T->Vnum; a++)
		vl[a]=ve[T->Vnum];
	while(!IsEmpty(Q)) {
		j=Pop(Q);
		for(p=T->List[j].next; p; p=p->next) {
			k=p->End;
			dut=p->value;
			if(vl[k]-dut<vl[j])
				vl[j]=vl[k]-dut;
		}
	}
	FILE*fp;
	fp=fopen("0071.txt","w");
	fclose(fp);
	for(j=1; j<=T->Vnum; j++)
		for(p=T->List[j].next; p; p=p->next) {
			k=p->End;
			dut=p->value;
			ee=ve[j];
			el=vl[k]-dut;
			if(ee==el)
				fp=fopen("0071.txt","a");
				fprintf(fp,"v%d",j);
				fclose(fp);
			break;
		}
		fp=fopen("0071.txt","a");
		fprintf(fp,"v%d",j-1);
		fclose(fp);
}

总代码如下

#include<stdio.h>
#include<stdlib.h>
typedef struct Edgelink {		//边链表
	int End;
	int value;
	struct Edgelink *next;
} Edge,*Elink;

typedef struct Vertexlink {		//顶点数组
	int Begin;
	int indegree;
	int Earliest;
	int Lastest;
	Elink next;
} Vertex[100];

typedef struct Graph {
	int Vnum;                   //顶点数目
	int Enum;
	Vertex List;
} Graph;

typedef struct SNode *stack;
struct SNode {
	int Data;
	struct SNode *next;
};

int ve[100];
int vl[100];

void CreateLink(Graph *T) {								//图的创建
	int temp;
	int i,j=1;
	FILE *fp;
	fp=fopen("007.txt","r");
	fscanf(fp,"%d",&T->Vnum);
	fscanf(fp,"%d",&T->Enum);
	for(i=1; i<=T->Enum; i++) {
		fscanf(fp,"%d",&temp);
		if(i==1||temp!=T->List[j-1].Begin) {
			T->List[j].Begin=temp;
			T->List[j].indegree=0;
			T->List[j].next=NULL;
			j++;
		}
		Elink p,q;
		p=(Edge*)malloc(sizeof(Edge));
		fscanf(fp,"%d",&(p->End));
		fscanf(fp,"%d",&(p->value));
		p->next=NULL;
		if(T->List[j-1].next==NULL)
			T->List[j-1].next=p;
		else {
			q = T->List[j-1].next;
			while(q->next) {
				q=q->next;
			}
			q->next=p;
		}
	}
	T->List[j].Begin=T->Vnum;
	T->List[j].indegree=0;
	T->List[j].next=NULL;
	fclose(fp);
}

void Indegree(Graph *T) {
	Elink p;
	int i=1,j,k;
	k=T->Vnum;
	int indegree[10]= {0};
	for(j=1; j<k; j++) {
		p=T->List[j].next;
		do {
			for(i=1; i<=k; i++) {
				if(i==p->End) {
					indegree[i]++;
				}
			}
			p=p->next;
		} while(p!=NULL);
	}
	for(i=1; i<=k; i++) {
		T->List[i].indegree=indegree[i];
		//printf("%d",indegree[i]);
	}
}

stack CreateStack() {
	stack S;
	S=(stack)malloc(sizeof(struct SNode));
	S->next=NULL;
	return S;
}

int IsEmpty(stack S) {
	return (S->next==NULL);
}

void Push(stack S,int item) {
	struct SNode *Tmpcell;
	Tmpcell=(struct SNode*)malloc(sizeof(struct SNode));
	Tmpcell->Data=item;
	Tmpcell->next=S->next;
	S->next=Tmpcell;
}

int Pop(stack S) {
	struct SNode *FirstCell;
	int TopElem;
	if(IsEmpty(S)) {
		printf("堆栈空");
		return ;
	} else {
		FirstCell=S->next;
		S->next=FirstCell->next;
		TopElem=FirstCell->Data;
		free(FirstCell);
		return TopElem;
	}
}

stack TopOrder(Graph *T) {
	int i,j,k,count=0;
	stack S,Q;
	S=CreateStack();
	Q=CreateStack();
	Elink p;
	for(i=1; i<T->Vnum; i++) {
		if(T->List[i].indegree==0) {
			Push(S,i);
		}
	}
	for(i=1; i<=T->Vnum; i++) {
		ve[i]=0;
	}
	while(!IsEmpty(S)) {
		j=Pop(S);
		Push(Q,j);
		++count;
		for(p=T->List[j].next; p; p=p->next) {
			k=p->End;
			if(--T->List[k].indegree==0)
				Push(S,k);
			if(ve[j]+p->value>ve[k])
				ve[k]=ve[j]+p->value;
		}
	}
	if(count<T->Vnum)
		return 0;
	else
		return Q;
}

void CriticalPath(Graph *T) {
	int a,j,k,el,ee,dut;
	char tag;
	Elink p;
	stack Q;
	Q=TopOrder(T);
	vl[1]=0;
	for(a=2; a<=T->Vnum; a++)
		vl[a]=ve[T->Vnum];
	while(!IsEmpty(Q)) {
		j=Pop(Q);
		for(p=T->List[j].next; p; p=p->next) {
			k=p->End;
			dut=p->value;
			if(vl[k]-dut<vl[j])
				vl[j]=vl[k]-dut;
		}
	}
	FILE*fp;
	fp=fopen("0071.txt","w");
	fclose(fp);
	for(j=1; j<=T->Vnum; j++)
		for(p=T->List[j].next; p; p=p->next) {
			k=p->End;
			dut=p->value;
			ee=ve[j];
			el=vl[k]-dut;
			if(ee==el)
				fp=fopen("0071.txt","a");
				fprintf(fp,"v%d",j);
				fclose(fp);
			break;
		}
		fp=fopen("0071.txt","a");
		fprintf(fp,"v%d",j-1);
		fclose(fp);
}
int main() {
	Graph *S;
	S = (Graph*)malloc(sizeof(Graph));
	CreateLink(S);
	Indegree(S);
	CriticalPath(S) ;
	return 0;
}

输入样例

 

输出样例

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值