7-34 任务调度的合理性(拓扑排序)

假定一个工程项目由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其它一些子任务后才能执行。“任务调度”包括一组子任务、以及每个子任务可以执行所依赖的子任务集。

比如完成一个专业的所有课程学习和毕业设计可以看成一个本科生要完成的一项工程,各门课程可以看成是子任务。有些课程可以同时开设,比如英语和C程序设计,它们没有必须先修哪门的约束;有些课程则不可以同时开设,因为它们有先后的依赖关系,比如C程序设计和数据结构两门课,必须先学习前者。

但是需要注意的是,对一组子任务,并不是任意的任务调度都是一个可行的方案。比如方案中存在“子任务A依赖于子任务B,子任务B依赖于子任务C,子任务C又依赖于子任务A”,那么这三个任务哪个都不能先执行,这就是一个不可行的方案。你现在的工作是写程序判定任何一个给定的任务调度是否可行。

输入格式:

输入说明:输入第一行给出子任务数N(≤100),子任务按1~N编号。随后N行,每行给出一个子任务的依赖集合:首先给出依赖集合中的子任务数K,随后给出K个子任务编号,整数之间都用空格分隔。

输出格式:

如果方案可行,则输出1,否则输出0。

输入样例1:

12
0
0
2 1 2
0
1 4
1 5
2 3 6
1 3
2 7 8
1 7
1 10
1 7

输出样例1:

1

输入样例2:

5
1 4
2 1 4
2 2 5
1 3
0

输出样例2:

0

  

分析:

       首先看百度百科上关于拓扑排序的定义:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

       拓扑序列中除了顶点的所有点都有前驱,即入度不为0。那么如果我们想要找顶点也很简单,只需要在一开始选择入度为零的点即可。将该点送入队列,删除该点及相关的边,更新入度数组,找出新的度为零的点(可能是多个,拓扑序列因此也不唯一)。

       简单说来,拓扑排序算法(之一)的步骤为:

       ①找出入度为0的点,并进入队列

       ②当队列不为空,从队首取得一个元素a,cnt(记录个数)加1,与a相连的点入度减一,如果更新的入度为0,则进入队列。

       为什么这么做就可以确定一个DAG(Directed Acyclic Graph)中是否有拓扑序列呢?个人是这样理解的,一开始没有前驱的点必定是顶点,否则其他点是无法到达的。将与该点相关的边删除后,选择度为0的点,这些点除了当前点是没有其他路径可以到达的。那么选择入度为0的点,选遍所有点,即可得到一个拓扑序列。现在只有一个问题,就是删除队列中现有点及其边之后,每次更新入度数组后是否能够保证总会出现度为0的点?

       为了解决这个问题,我们可以采用假设法。假设剩余的n个点入度都大于等于1,你会发现这个子图就不再是有向无环图了。我们开始的图是DAG,那么它的子图也是DAG,既然有向无环,那么必定有入度为0的点。

       代码中TopNum数组用来记录选择出的拓扑序列,虽然对于本题是无用的……但我还是写了上去。如下:

#include<iostream>

using namespace std;

void Topsort(int graph[][101], int NumVertex);

int main(){
	int graph[101][101];
	int N, task, pretask;
	for(int i = 0; i < 101; i++)
		for(int j = 0; j < 101; j++)
			graph[i][j] = 0;
	cin >> N;
	for(int i = 0; i < N; i++){
		cin >> task;
		if(task != 0){
			for(int j = 0; j < task; j++){
				cin >> pretask;
				graph[pretask][i + 1] = 1;
			}
		}
	}
	Topsort(graph, N);	
}

void Topsort(int graph[][101], int NumVertex){
	int TopNum[101], Indegree[101];
	int queue[101], head = 0, tail = 0;
	int cnt = 0, V, W;
	//Create queue and make it empty
	for(int i = 0; i < 101; i++)
		queue[i] = -1;
	//Initial Indegree array
	for(int i = 1; i <= NumVertex; i++)
		Indegree[i] = 0;
	//find vertexes whose indegree is zero and put vertexes into the queue 
	//Set the Indegree array
	for(int i = 1; i <= NumVertex; i++){
		int flag = 1, j;
		for(j = 1; j <= NumVertex; j++){
			if(graph[j][i] == 1){
				flag = 0;
				Indegree[i]++;
			}
		}
		if(flag){
			queue[++tail] = i;
		}
	}
	//when queue is not empty
	while(head != tail){
		V = queue[++head];						
		TopNum[V] = ++cnt;
		for(W = 1; W <= NumVertex; W++){
			if(graph[V][W] == 1){
				if(--Indegree[W] == 0)
					queue[++tail] = W;
			}
		}
	}
	if(cnt != NumVertex)
		cout << '0';
	else
		cout << '1';
}
伪码:
TopSort(){
	计算每个顶点的入度InDegree[],若入度为0,入队
	while(队不空){
		出队顶点v
		输出v,计数count++
		对于每个邻接自v的顶点w:InDegree[w]减1,若变为0则入队 
	} 
	if(count != N) 错误:不存在拓扑排序序列(有环) 
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 任务调度合理性是指在任务执行的过程中,根据任务的优先级、紧急程度、资源需求等因素,合理地安排任务的执行顺序和时间,以达到最优的执行效果。合理的任务调度可以提高系统的效率和稳定性,减少资源的浪费和冲突,提高任务的执行质量和效率。同时,合理的任务调度还可以提高系统的可靠性和可维护性,降低系统的故障率和维护成本。因此,任务调度合理性对于系统的正常运行和发展至关重要。 ### 回答2: 任务调度合理性是指,在多个任务需要同时执行时,如何合理地分配和调度它们的执行顺序和资源分配,以便实现最优的执行效率和资源利用率。 首先,任务调度合理性可以提高系统的效率和资源利用率。在多任务系统中,当任务数量超过系统的处理能力时,任务调度可以合理分配处理器和其他资源,使得系统的处理能力能够得到最大化的利用,从而提高系统的效率和资源利用率。 其次,任务调度合理性还可以减少系统的响应时间和延迟。当系统中有大量的任务需要处理时,任务调度可以根据任务的优先级和紧急程度来合理分配处理时间,使得系统对高优先级的任务能够及时响应,并在最短时间内完成。 此外,任务调度合理性也可以提高系统的可靠性和安全性。通过对任务的调度和资源分配进行科学合理的规划和设计,能够有效避免资源争用和死锁等问题,保证系统的稳定性和可靠性,同时也能够保障系统的安全性。 综上所述,任务调度合理性是多任务系统中非常重要的一个方面。通过合理的任务调度和资源分配,可以最大程度地提高系统的效率和资源利用率,降低系统的响应时间和延迟,同时还可以保证系统的可靠性,安全性和稳定性,从而实现系统的高效运行。 ### 回答3: 任务调度是指操作系统对计算机中各个任务进行合理的分配和调度,优化系统资源的利用,提高计算机系统的效率和性能。在实际应用中,任务调度可以分为多类,其中包括进程调度、作业调度、实时调度等等。在这些调度过程中,一个重要的问题是如何将任务合理地分配给计算机系统的资源,以便最大化地利用系统的性能。 7-5任务调度合理性,是指任务调度与目标之间的联系是否相符。任务调度应当遵循任务的性质,确定任务的优先级,按照优先级高低或特定的调度算法来决定任务的执行顺序,以达到最优的系统性能。同时,任务调度也需要及时响应用户的请求,减少系统的延迟和响应时间,保证系统的实时性和可靠性。 任务调度合理性还需要考虑计算机系统的硬件资源和软件资源,包括CPU、内存、硬盘、网络带宽等等。在任务的分配和调度过程中,应考虑这些资源的使用情况和负载情况,避免资源的浪费和过度使用,保护系统的健康和稳定。 任务调度合理性对于计算机系统的性能和效率至关重要,它可以使计算机系统在繁忙的工作环境下高效地工作,避免系统出现过度负载或资源浪费的情况。合理的任务调度可以减少系统的延迟和响应时间,提高用户的交互体验和满意度,同时也可以减少系统的能耗和成本,保护环境和资源。 总之,任务调度合理性对于计算机系统的性能和效率有着至关重要的作用。在实际应用中,任务调度应遵循任务性质、优先级等因素,同时考虑计算机系统的硬件和软件资源负载情况,以达到最优的系统性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值