上数据结构学的一种生产计划图

这个数据结构可以反映项目的开始和完成时间,感觉是数据结构的图的一个比较具体的应用。
后面是完整版代码:

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

/*作业数据*/ 
typedef struct _data{
	int id;
	char name[20];
	int duration;
	int tes;
	int tef;
	int tls;
	int tlf;
	int crutical;
//	int done;
}data;

/*作业关系*/
typedef struct _relation{
	data *d;
	struct _relation *prev,*next;
}relation;

/*作业*/
typedef struct _task{
	data *d;
	relation *predecessor,*successor;
	struct _task *next,*prev;
}task;

/*项目*/
typedef struct _pert{
	task *head,*tail;
	int tes;  //最早开工时间
	int tlf;  //项目完工时间
	char name[20]; 
	int id;
}pert;

int max(int a,int b){
	return (a>b?a:b);
}

int min(int a,int b){
	return (a<b?a:b);
}

int pert_add_task(pert *p,data *d){
	task *t = (task *)malloc(sizeof(task));
	if(t==NULL){
		return 0;
	}
	t->d=d;
	t->predecessor=NULL;
	t->successor=NULL;
	t->next=NULL;
	t->prev=NULL;
	
	if(p->head==NULL){
		p->head=t;
		p->tail=t;
	}else{
		t->prev=p->tail;
		p->tail->next=t;
		p->tail=t;
	}
	
	return -1;
}

void pert_iterate(pert *p){
	task *t = p->head;
	while(t!=NULL){
		//查找紧前节点
		relation *pr = t->predecessor;
		while(pr!=NULL){
			printf("%d<-",pr->d->id);
			pr=pr->next;
		} 
		
		printf("[%d]",t->d->id);
		
		//查找紧后节点
		relation *sr = t->successor;
		while(sr!=NULL){
			printf("->%d",sr->d->id);
			sr=sr->next; 
		} 
		
		printf("\n");
		t=t->next;
	}
}

task *pert_find_task(pert *p,int id){
	task *t=p->head;
	while(t!=NULL){
		if(t->d->id==id){
			return(t);
		}
		
		t=t->next;
	}
	
	return(NULL);
}

relation *pert_find_predecessor(pert *p,int id,int pid){
	task *t=pert_find_task(p,id);
	if(p==NULL){
		return(NULL);
	}
	
	relation *pr=t->predecessor;
	while(pr!=NULL){
		if(pr->d->id==pid){
			return(pr);
		}
		pr=pr->next;
	}
	
	return(NULL);
}

relation *pert_find_successor(pert *p,int id,int pid){
	task *t=pert_find_task(p,id);
	if(p==NULL){
		return(NULL);
	}
	
	relation *sr=t->successor;
	while(sr!=NULL){
		if(sr->d->id==pid){
			return(sr);
		}
		sr=sr->next;
	}
	
	return(NULL);
}

/*pid-predecessor, sid-successor*/
int pert_add_relation(pert *p,int pid,int sid){
	//查找作业
	task *pt=pert_find_task(p,pid);
	if(pt==NULL){
		printf("\n%d not exists!",pid);
		return(0);
	} 
	
	task *st=pert_find_task(p,sid);	
	if(st==NULL){
		printf("\n%d not exists!",sid);
		return(0);
	}
	
	/*判断是否存在*/
	relation *tr=pert_find_predecessor(p,sid,pid);
	if(tr!=NULL){
		printf("This relation has existed!\n");
		return(0);
	}
	
	tr=pert_find_successor(p,pid,sid);
	if(tr!=NULL){
		printf("This relation has existed!\n");
		return(0);
	}
	
	//增加紧前关系
	relation *pr=(relation *)malloc(sizeof(relation));
	if(pr==NULL){
		return(0);
	}
	pr->d=pt->d;
	pr->next=NULL;
	pr->prev=NULL;
	
	if(st->predecessor==NULL){
		st->predecessor=pr;
	}else{
		st->predecessor->prev=pr;
		pr->next=st->predecessor;
		st->predecessor=pr;
	}
	//增加紧后关系 
	relation *sr=(relation *)malloc(sizeof(relation));
	if(sr==NULL){
		return(0);
	}
	sr->d=st->d;
	sr->next=NULL;
	sr->prev=NULL;
	
	if(pt->successor==NULL){
		pt->successor=sr;
	}else{
		sr->next=pt->successor;
		pt->successor->prev=sr;
		pt->successor=sr;
	}
	
	return(-1);
}

int pert_delete_relation(pert *p,int pid,int sid){
	task *pt=pert_find_task(p,pid);
	if(pt==NULL){
		return(0);
	}
	
	task *st=pert_find_task(p,sid);
	if(st==NULL){
		return(0);
	}
	
	//删除紧后关系
	relation *sr=pt->successor;
	while(sr!=NULL){
		if(sr->d->id==sid){
			if(sr->prev==NULL){
				pt->successor=sr->next;
			}else if(sr->next==NULL){
				sr->prev->next=NULL;
			}else{
				sr->next->prev=sr->prev;
				sr->prev->next=sr->next;
			}
			
			free(sr);
			sr=NULL; 
			break;
		}
		sr=sr->next;
	}
	 
	//删除紧后关系
	relation *pr=st->predecessor;
	while(pr!=NULL){
		if(pr->d->id==pid){
			if(pr->prev==NULL){
				st->predecessor=pr->next;
			}else if(pr->next==NULL){
				pr->prev->next=NULL;
			}else{
				pr->next->prev=pr->prev;
				pr->prev->next=pr->next;
			}
			
			free(pr);
			sr=NULL; 
			break;
		}
		pr=pr->next;
	}
	
	return(-1);
}

int pert_delete_task(pert *p,int id){
	/*1)删除紧前和紧后*/
	task *t=pert_find_task(p,id);
	//删除紧前作业 
	relation *pr=t->predecessor;
	while(pr!=NULL){
		task *pt=pert_find_task(p,pr->d->id);
		pert_delete_relation(p,pt->d->id,id);
		
		pr=t->predecessor;
	}
	
	//删除紧后作业
	relation *sr=t->successor;
	while(sr!=NULL){
		task *st=pert_find_task(p,sr->d->id);
		pert_delete_relation(p,id,st->d->id);
		
		sr=t->successor;
	} 
	
	/*2)删除作业本身*/ 
	t=p->head;
	while(t!=NULL){
		if(t->d->id==id){
			if(p->head->d->id==id&&p->tail->d->id==id){
				p->head=NULL;
				p->tail=NULL;
			}else if(p->head->d->id==id){
				p->head=t->next;
				t->next->prev=NULL;
			}else if(p->tail->d->id==id){
				p->tail=t->prev;
				t->prev->next=NULL;
			}else{
				t->next->prev=t->prev;
				t->prev->next=t->next;
			}
			
			free(t->d);
			free(t);
			break;
		}
		
		t=t->next;
	}
}

/*
1. 阈值问题: tls-tes<d
2. 某些作业它们的开完工时间是事先确定,不能改变 
3. 紧前紧后关系:1)fs=finish-start; 2)ss=start-start; 3)ff=finish-finish; 4)sf=start-finish;
4. finish+delta=start
5. 工厂日历 :worktime/working-shift 
6. 可视化:pert图,GANTT图 
*/
int pert_schedule(pert *p){
	/*初始化*/ 
	task *t=p->head;
	while(t!=NULL){
		t->d->tef=0;
		t->d->tes=0;
		t->d->tlf=0;
		t->d->tls=0;
		//t->d->done=0;
		
		t=t->next;
	}
	
	/*顺排计划*/
	while(1){
		task *t=p->head;
		int c1=0,c2=0;   //c1表示还未算出的作业数目,c2表示该轮循环算出的作业个数 
		while(t!=NULL){
			if(t->d->tes==0&&t->d->tef==0){
				c1++;
			}
			int done=1;
			int tes=0;
			relation *r=t->predecessor;
			while(r!=NULL){
				if(r->d->tef==0){
					done=0;
					break;
				}
				tes=max(tes,r->d->tef);
				r=r->next;
			}
			if(done==1){
				c2++;
				t->d->tes=tes;
				t->d->tef=tes+t->d->duration;
			}
			t=t->next;
		}
		if(c1==0){
			break;
		}
		//环判断
		if(c1>0&&c2==0){
			printf("存在环!");
			return(0); 
		}
		
	}
	
	/*倒排计划*/
	int maxTef=0;
	t=p->head;
	while(t!=NULL){
		maxTef=max(maxTef,t->d->tef);
		
		t=t->next;
	}
	
	while(1){
		int c1=0,c2=0;
		task *t=p->head;
		while(t!=NULL){
			if(t->d->tlf==0){
				c1++;
			}else{
				t=t->next;
				continue;
			}
			
			//判断该作业的紧前作业是否完成
			int done=1;
			int tlf=maxTef;
			relation *r=t->successor;
			while(r!=NULL){
				if(r->d->tlf==0){
					done=0;
					break;
				}
				tlf=min(tlf,r->d->tls);
				r=r->next;
			}
			
			if(done==1){
				c2++;
				t->d->tlf=tlf;
				t->d->tls=tlf-t->d->duration;
			}
			
			t=t->next;
		}
		
		if(c1==0){
			break;
		}
			
		if(c1>0&&c2==0){
			printf("存在环!");
			return(0);
		}
	}
	
	/*关键作业*/
	t=p->head;
	while(t!=NULL){
		if(t->d->tes==t->d->tls){
			t->d->crutical=1;
		}else{
			t->d->crutical=0;
		}
		t=t->next;
	} 
}


void pert_iterate_time(pert *p){
	task *t=p->head;
	while(t!=NULL){
		printf("%d:\ttes:%d\ttef:%d\ttls:%d\ttlf:%d\tcrutical:%d\n",t->d->id,t->d->tes,t->d->tef,t->d->tls,t->d->tlf,t->d->crutical);
		
		t=t->next;
	}
}


int main(int argc, char *argv[]) {
	pert *p=(pert *)malloc(sizeof(pert));
	if(p==NULL){
		return(0);
	}
	p->id=1;
	p->tes=0;
	p->tlf=0;
	p->head=NULL;
	p->tail=NULL;
	
	int i;
	for(i=1;i<=5;i++){
		data *d=(data *)malloc(sizeof(data));
		d->id=i;
		d->duration=i;
		pert_add_task(p,d);
	}
	pert_add_relation(p,1,2);
	pert_add_relation(p,1,3);
	pert_add_relation(p,2,4);
	pert_add_relation(p,3,4);
	pert_add_relation(p,4,5);
	pert_add_relation(p,4,5);
	
	//pert_schedule(p);
	pert_iterate(p);
	/*
	printf("删除关系2-4:\n");
	pert_delete_relation(p,2,4);
	pert_iterate(p);
	
	printf("删除作业2:\n");
	pert_delete_task(p,2);
	pert_iterate(p);
	*/
	
	printf("计划测试:\n");
	pert_schedule(p);
	pert_iterate_time(p);
}

这个数据结构是我们老师教我们的,还没有在别的书上看到过。在这里写一个博客备忘。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值