文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

用C语言递归实现火车调度算法详解

2024-04-02 19:55

关注

笔者在李云清版的《数据结构》中第二章遇到了这道经典的火车调度题,经过对一些前辈的代码进行学习,以下将这段火车代码进行分析详解,不对之处,还请各位大佬指示,不胜感激!

1、代码

题目如下:
2.8编号为1,2,3,4的四列火车通过一个栈式的列车调度站,可能得到的调度结果有哪些?如果有n列火车通过调度站,请设计一个算法,输出所有可能的调度结果。

算法运用的思想是运用栈+递归,算法的难点也在于此。先上代码:


#include <stdio.h>
#define MAX 100
typedef struct s{
	char a[MAX];
	int top;
}Stack;

Stack S;

char d[MAX],seq[MAX];

int len; 
int count=0;

void initStack(Stack *S) 
{
	S->top=-1;
}

void push(Stack *S,char x) 
{
	if(S->top>=MAX) return;
	S->top++;
	S->a[S->top]=x;
}

char pop(Stack *S) 
{
	if (S->top==-1) 
	{ printf("ERROR, POP Empty Stack");  
	return -1; 
    }  
	S->top--;    
	return S->a[S->top+1];  
} 

int isEmpty(Stack *S)  
{     
	if (S->top==-1) return 1; 
	return 0; 
} 

void outSeq(char *seq, int len)  
{    
	int i; 
	for(i=0; i<len; i++)  
	printf("%2c",seq[i]); 
	printf("\n"); 
} 

void scheduler(int pos, int seq_pos)
{     
	int i=0;char t; 
 
	if(pos<len){
		 
	push(&S,d[pos]); 
	scheduler(pos+1,seq_pos); 
	pop(&S); 
	} 
	if (!isEmpty(&S)){ 
	t=pop(&S); 
	seq[seq_pos++]=t; 
	scheduler(pos,seq_pos); 
	push(&S,t); 
	} 
	if (pos>=len && isEmpty(&S))  
	{ outSeq(seq,len); count++; } 
}

int main(){ 
   int i; 
   printf("\nplease input the num be scheduled: "); 
   scanf("%d", &len);  
   for(i=0; i<len; i++) 
     d[i]='1'+i;  
   printf("the original seq is:"); 
   outSeq(d,len); 
   initStack(&S); 
   scheduler(0,0); 
   printf("\n count=%d", count); 
   return 0; 
} 

输入3(即三列火车),得到的结果如下:

在这里插入图片描述

2、代码详解

本算法主要是运用了栈+递归+回溯的思想,主要的代码块有三个:
代码块1


if(pos<len){	
	push(&S,d[pos]); 
	scheduler(pos+1,seq_pos); 
	pop(&S); 
	} 

代码块2


if (!isEmpty(&S)){
	t=pop(&S); 
	seq[seq_pos++]=t; 
	scheduler(pos,seq_pos); 
	push(&S,t); 
	}

代码块3


if (pos>=len && isEmpty(&S))  
	{ outSeq(seq,len); count++; } 

这里需要注意的是判定元素pos,是处理原始数据中第pos个元素,pos从0开始
代码块1根据你输入的len和第pos个元素来判定是否执行代码块1
例如当你输入了3,
通过代码


scanf("%d", &len);
   for(i=0; i<len; i++) 
     d[i]='1'+i; 

即有三列火车,分别代号为1,2,3
数组d中的位置分别是0,1,2

当代码第一次执行


void scheduler(int pos, int seq_pos)

函数的时候,进入了判定
此时参数pos和seq_pos都为0
那么0<len=3,执行代码块1
代码块1把数组第0个元素压入栈中,即1号火车进入车站

接着进行第一次调用函数scheduler

此时参数pos为1,seq_pos为0
因为1<3,继续执行代码块1
代码块1把数组第1个元素压入栈中,即2号火车进入车站

进行第二次调用函数scheduler

此时参数pos为2,seq_pos为0
因为2<3,继续执行代码块1
代码块1把数组第2个元素压入栈中,即3号火车进入车站

进行第三次调用函数scheduler

此时参数pos为3,seq_pos为0
因为3=len=3,所以开始执行代码块2

在代码块2中,把栈顶的元素赋值给t,同时把t放入seq数组的第0个位置中,seq++
即3号列车驶出火车站

进行第四次调用函数sceduler

此时参数pos=3,seq_pos=1
继续执行代码块2,把栈顶的元素赋值给t,同时把t放入seq数组的第1个位置中,seq++
即2号列车驶出火车站

进行第五次调用函数sceduler

此时参数pos=3,seq_pos=2
继续执行代码块2,把栈顶的元素赋值给t,同时把t放入seq数组的第2个位置中,seq++
即1号列车驶出火车站

进行第六次调用函数scheduler

此时参数pos=3,seq_pos=3,现在的情况是三列火车都已经驶出火车站了,也就是栈已经空了,同时满足pos>=len的条件,所以执行代码块3

代码块3把结果进行了输出,
输出结果是3,2,1
第六次调用函数scheduler整个过程结束

此时,代码开始进行回溯

回到了第五次调用函数scheduler
代码块2中scheduler执行完,执行push,也就是压栈操作,可是现在已经没有火车进站了,因为三列火车都已经走了

代码回到了第四次调用函数scheduler
代码块2中scheduler执行完,执行push,也就是压栈操作,也没有火车能进车站了
为什么?
还记不记得这个时候是3号列车和2号列车已经出去了,1号列车在车站里,所以没有多余的进站的车了

代码代码回到了第三次调用函数scheduler
还记不记得这个时候是3号列车、已经出去了,1号列车和2号列车在车站里,所以没有多余的进站的车了

代码代码回到了第二次调用函数scheduler

代码重新回到了代码块1

注意,是代码块1

此时,执行了pop,也就是进行了出栈操作
什么意思?
栈顶的3号列车驶出了车站

这里是笔者出现了思维误区的地方,读者不理解递归思想的需要特别注意,当时我在想,3号列车驶出后是不是回到了第一次调用函数?忽略了下面的if语句,错误的认为执行了代码块1后不会执行代码块2,混淆了if-else和if,if语句的关系

代码1执行完,开始执行代码2
注意此时的列车只有两辆,是1号列车和2号列车,参数是pos=2,seq_pos=0

代码块2进行了出栈操作,让在栈顶的2号列车出车站,然后seq_pos++

进行第七次调用函数sceduler

此时代码参数pos=2,seq_pos=1
pos=2<len=3,进入代码块1
代码块1把pos=2的元素压入栈中
什么意思?
把三号列车驶入车站

进行第八次调用函数sceduler

此时代码参数pos=3,seq_pos=1
pos=3=len=3,进入代码块2
代码块2进行了出栈操作,让在栈顶的3号列车出车站
然后seq_pos++

进行第九次调用函数scheduler

此时代码参数pos=3,seq_pos=2
pos=3=len=3,进入代码块2
代码块2进行了出栈操作,让在栈顶的1号列车出车站
然后seq_pos++

进行第十次调用函数scheduler

pos=3=len=3,同时栈里的三辆列车已经全部驶出车站了,所以进行执行代码块3
代码块3把结果进行了输出
输出结果是2,3,1

以此类推…

3、用二叉树表示调用过程

左子树表示压栈(进站),右子树表示出栈(驶出车站),线上数字表示调用函数次数,负数表示出栈,例如-1表示1号列车驶出车站

在这里插入图片描述

4、思维导图

在这里插入图片描述

本文代码参考自李云清《数据结构》第三版课本习题火车调度算法答案

本文有参考作者@littlehedgehog的火车调度详解,但作者@littlehedgehog并未对代码块1中pop的作用和代码块2中push进行分析,在此表示感谢

到此这篇关于用C语言递归实现火车调度算法详解的文章就介绍到这了,更多相关用C语言递归实现火车调度算法详解内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯