数据结构课程的大作业,大致要求是利用树做一个WBS模型并在WBS的基础上利用有向图构建计划制定模型。计划制定模型要求能够检查环,能实现顺排和倒排,工作日历要能跳过周末安排任务,要实现根据自定义的delta值实现关键路径的查找。
想着很久也没写过什么了,而且这个代码老师打分了之后也没说对不对,所以分享这个代码也是请大家看看这个代码的不足和改进之处。
这个程序用C语言实现的,代码如下:
#include <stdio.h>
#include <stdlib.h>
/*作业数据*/
typedef struct _data{
int id;
char name[20];
int duration;
struct _calendar *c;
int critical;
}data;
/*工作活动*/
typedef struct _activity{
int aid;
char name[20];
struct _activity *parent,*next_sibling,*prev_sibling,*first_child,*last_child;
struct _task *first_task;
}node;
/*作业*/
typedef struct _task{
data *d;
node *parent; //这个是作业所属的活动
struct _relation *predecessor,*successor;
//这个为了兼容在有向图中的task添加的,树形结构中的兄弟节点使用next_task和prev_task表示
struct _task *next,*prev;
struct _task *prev_task,*next_task;
}task;
/*紧前紧后作业关系*/
typedef struct _relation{
struct _relation *next,*prev;
data *d;
}relation;
/*项目(树)*/
typedef struct _tree{
int id;
char name[20];
node *root;
}tree;
/*项目(pert图)*/
typedef struct _pert{
int id; //这个项目的id号和name均从上面的项目树中获得
char name[20];
task *head,*tail;
struct _calendar *c;
}pert;
/*工作日历
区别一下叫new calendar简称ncalendar
(把年月日给录进去了)*/
typedef struct _calendar{
//顺排计划
int tesyear;
int tesmonth;
int tesday;
int tesweek; //项目开始的年月日以及星期数(顺排)
int tefyear;
int tefmonth;
int tefday;
int tefweek;
//倒排计划
int tlfyear;
int tlfmonth;
int tlfday;
int tlfweek; //项目结束的年月日以及星期数(倒排)
int tlsyear;
int tlsmonth;
int tlsday;
int tlsweek;
}ncalendar;
//用一个二维数组储存天数
//每月的天数,如果是闰年我们使用day_lab[1][month]
int day_lab[2][13] = {
{
0,31,28,31,30,31,30,31,31,30,31,30,31},{
0,31,29,31,30,31,30,31,31,30,31,30,31}};
//获取当前活动的下一个活动
node *tree_get_next(node *n){
if(n==NULL){
return(NULL);
}
if(n->first_child!=NULL){
return(n->first_child);
}else if(n->next_sibling!=NULL){
return(n->next_sibling);
}else{
node *t=n->parent;
while(t!=NULL&&t->next_sibling==NULL){
t=t->parent;
}
if(t!=NULL){
return(t->next_sibling);
}else{
return(NULL);
}
}
}
//获取当前活动的上一个活动
node *tree_get_prev(node *n){
if(n->prev_sibling!=NULL){
if(n->prev_sibling->last_child!=NULL){
node *t=n->prev_sibling->last_child;
while(t->last_child!=NULL){
t=t->last_child;
}
return(t);
}else{
return(n->prev_sibling);
}
}else{
if(n->parent!=NULL){
return(n->parent);
}else{
return(NULL);
}
}
}
//获取当前活动下的最后一个活动(这个主要用于重构活动或剪枝)
node *tree_get_last_child(node *n){
while(n!=NULL && n->last_child!=NULL){
n=n->last_child;
}
return(n);
}
//查找活动
node *tree_find_node(tree *t,int aid){
node *n=t->root;
while(n!=NULL){
if(n->aid==aid){
return(n);
}
n=tree_get_next(n);
}
return(NULL);
}
//遍历活动(为了获得较好的层次显示效果这里不使用tree_get_next函数)
void *tree_iterate(tree *tr){
node *n=tr->root;
int i=0;
//遍历整棵树
while(n!=NULL){
int j;
printf("%d:%s\n",n->aid,n->name);
//查看是否有任务
if(n->first_task!=NULL){
task *t1=n->first_task;
while(t1!=NULL){
for(j=0;j<i;j++){
printf(" ");
}
printf("#task:%d:%s\n",t1->d->id,t1->d->name);
t1=t1->next_task;
}
}
//为打印下一个node活动做准备
if(n->first_child!=NULL){
i++;
n=n->first_child;
}else if(n->next_sibling!=NULL){
n=n->next_sibling;
}else{
node *t=n->parent;
i--;
while(t!=NULL&&t->next_sibling==NULL){
t=t->parent;
i--;
}
if(t!=NULL){
n=t->next_sibling;
}else{
n=NULL;
break;
}
}
for(j=0;j<i;j++){
printf(" ");
}
}
}
//增加活动
int tree_add_node(tree *t,int paid,int aid,char *name){
//1)查找父节点
node *p=tree_find_node(t,paid);
if(p==NULL && t->root!=NULL){
return(0);
}
//2)创建新节点
node *n=(node *)malloc(sizeof(node));
if(n==NULL){
printf("Memory overflow!\n");
return(0);
}
n->aid=aid;
strcpy(n->name,name);
n->first_child=NULL;
n->first_task=NULL;
n->last_child=NULL;
n->next_sibling=NULL;
n->parent=NULL;
n->prev_sibling=NULL;
//3)调整指针,把子节点加到父节点中
n->parent=p;
if(p==NULL){
//这里忘了考虑空树问题,应该是:如果树是空的,那么新节点就是根
t->root=n;
}else if(p->first_child==NULL){
p->first_child=n;
p->last_child=n;
}else{
/*加在头上
n->next_sibling=p->first_child;
p->first_child->prev_sibling=n;
p->first_child=n;
*/
/*加在尾上*/
n->prev_sibling=p->last_child;
p->last_child->next_sibling=n;
p->last_child=n;
}
return(-1);
}
int tree_empty(tree *t){
node *n=tree_get_last_child(t->root);
while(n!=NULL){
node *n1=tree_get_prev(n);
task *t1=n1->first_task;
while(n1->first_task!=NULL){
t1=n1->first_task;
n1->first_task=n1->first_task->next_task;
free(t1->d);
free(t1);
}
free(n)