这个数据结构可以反映项目的开始和完成时间,感觉是数据结构的图的一个比较具体的应用。
后面是完整版代码:
#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);
}
这个数据结构是我们老师教我们的,还没有在别的书上看到过。在这里写一个博客备忘。