数据结构课的大作业

数据结构课程的大作业,大致要求是利用树做一个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)
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值