- // algo3-9.cpp 用递归函数求解迷宫问题(求出所有解)
- #include"c1.h" // 根据《PASCAL程序设计》(郑启华编著)中的程序改编
- #include"func3-1.cpp" // 定义墙元素值为0,可通过路径为-1,通过路径为足迹
- void Try(PosType cur,int curstep)
- { // 由当前位置cur、当前步骤curstep试探下一点
- int i;
- PosType next; // 下一个位置
- PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}}; // {行增量,列增量},移动方向,依次为东南西北
- for(i=0;i<=3;i++) // 依次试探东南西北四个方向
- {
- next.x=cur.x+direc[i].x; // 根据移动方向,给下一位置赋值
- next.y=cur.y+direc[i].y;
- if(m[next.x][next.y]==-1) // 下一个位置是通路
- {
- m[next.x][next.y]=++curstep; // 将下一个位置设为足迹
- if(next.x!=end.x||next.y!=end.y) // 没到终点
- Try(next,curstep); // 由下一个位置继续试探(降阶递归调用,离终点更近)
- else // 到终点
- {
- Print(); // 输出结果(出口,不再递归调用)
- printf("/n");
- }
- m[next.x][next.y]=-1; // 恢复为通路,以便在另一个方向试探另一条路
- curstep--; // 足迹也减1
- }
- }
- }
- void main()
- {
- Init(-1); // 初始化迷宫,通道值为-1
- printf("此迷宫从入口到出口的路径如下:/n");
- m[begin.x][begin.y]=1; // 入口的足迹为1
- Try(begin,1); // 由第1步入口试探起
- }
- // algo3-1.cpp 调用算法3.1的程序
- #define N 8 // 定义待转换的进制N(2~9)
- typedef int SElemType; // 定义栈元素类型为整型
- #include"c1.h"
- #include"c3-1.h" // 采用顺序栈
- #include"bo3-1.cpp" // 利用顺序栈的基本操作
- void conversion() // 算法3.1
- { // 对于输入的任意一个非负10进制整数,打印输出与其等值的N进制数
- SqStack s;
- unsigned n; // 非负整数
- SElemType e;
- InitStack(s); // 初始化栈
- printf("将10进制整数n转换为%d进制数,请输入:n(>=0)=",N);
- scanf("%u",&n); // 输入非负十进制整数n
- while(n) // 当n不等于0
- {
- Push(s,n%N); // 入栈n除以N的余数(N进制的低位)
- n=n/N;
- }
- while(!StackEmpty(s)) // 当栈不空
- {
- Pop(s,e); // 弹出栈顶元素且赋值给e
- printf("%d",e); // 输出e
- }
- printf("/n");
- }
- void main()
- {
- conversion();
- }
- // algo3-2.cpp 改算法3.1,10进制→16进制
- typedef int SElemType; // 定义栈元素类型为整型
- #include"c1.h"
- #include"c3-1.h" // 采用顺序栈
- #include"bo3-1.cpp" // 利用顺序栈的基本操作
- void conversion()
- { // 对于输入的任意一个非负10进制整数,打印输出与其等值的16进制数
- SqStack s;
- unsigned n; // 非负整数
- SElemType e;
- InitStack(s); // 初始化栈
- printf("将10进制整数n转换为16进制数,请输入:n(>=0)=");
- scanf("%u",&n); // 输入非负十进制整数n
- while(n) // 当n不等于0
- {
- Push(s,n%16); // 入栈n除以16的余数(16进制的低位)
- n=n/16;
- }
- while(!StackEmpty(s)) // 当栈不空
- {
- Pop(s,e); // 弹出栈顶元素且赋值给e
- if(e<=9)
- printf("%d",e);
- else
- printf("%c",e+55); // 大于9的余数,输出相应的字符
- }
- printf("/n");
- }
- void main()
- {
- conversion();
- }
- // algo3-4.cpp 行编辑程序,实现算法3.2
- typedef char SElemType;
- #include"c1.h"
- #include"c3-1.h"
- #include"bo3-1.cpp"
- FILE *fp;
- void copy(SElemType c)
- { // 将字符c送至fp所指的文件中
- fputc(c,fp);
- }
- void LineEdit()
- { // 利用字符栈s,从终端接收一行并送至调用过程的数据区。算法3.2
- SqStack s;
- char ch;
- InitStack(s);
- printf("请输入一个文本文件,^Z结束输入:/n");
- ch=getchar();
- while(ch!=EOF)
- { // 当全文没结束(EOF为^Z键,全文结束符)
- while(ch!=EOF&&ch!='/n')
- { // 当全文没结束且没到行末(不是换行符)
- switch(ch)
- {
- case '#':if(!StackEmpty(s))
- Pop(s,ch); // 仅当栈非空时退栈,c可由ch替代
- break;
- case '@':ClearStack(s); // 重置s为空栈
- break;
- default :Push(s,ch); // 其他字符进栈
- }
- ch=getchar(); // 从终端接收下一个字符
- }
- StackTraverse(s,copy); // 将从栈底到栈顶的栈内字符传送至文件
- fputc('/n',fp); // 向文件输入一个换行符
- ClearStack(s); // 重置s为空栈
- if(ch!=EOF)
- ch=getchar();
- }
- DestroyStack(s);
- }
- void main()
- {
- fp=fopen("ed.txt","w"); // 在当前目录下建立ed.txt文件,用于写数据,
- if(fp) // 如已有同名文件则先删除原文件
- {
- LineEdit();
- fclose(fp); // 关闭fp所指的文件
- }
- else
- printf("建立文件失败!/n");
- }
- // algo3-3.cpp 括号(()、[]和{})匹配的检验
- typedef char SElemType;
- #include"c1.h"
- #include"c3-1.h"
- #include"bo3-1.cpp"
- void check()
- { // 对于输入的任意一个字符串,检验括号是否配对
- SqStack s;
- SElemType ch[80],*p,e;
- InitStack(s); // 初始化栈
- printf("请输入带括号(()、[]和{})的表达式/n");
- gets(ch);
- p=ch; // p指向字符串的首字符
- while(*p) // 没到串尾
- switch(*p)
- {
- case '(':
- case '[':
- case '{':Push(s,*p++); // 左括号入栈,且p++
- break;
- case ')':
- case ']':
- case '}':if(!StackEmpty(s)) // 栈不空
- {
- Pop(s,e); // 弹出栈顶元素
- if(!(e=='('&&*p==')'||e=='['&&*p==']'||e=='{'&&*p=='}'))
- { // 出现3种匹配情况之外的情况
- printf("左右括号不配对/n");
- exit(ERROR);
- }
- }
- else // 栈空
- {
- printf("缺乏左括号/n");
- exit(ERROR);
- }
- default: p++; // 其它字符不处理,指针向后移
- }
- if(StackEmpty(s)) // 字符串结束时栈空
- printf("括号匹配/n");
- else
- printf("缺乏右括号/n");
- }
- void main()
- {
- check();
- }
- // algo3-5.cpp 利用栈求解迷宫问题(只输出一个解,算法3.3)
- #include"c1.h"
- #include"func3-1.cpp"
- int curstep=1; // 当前足迹,初值(在入口处)为1
- struct SElemType // 栈的元素类型
- {
- int ord; // 通道块在路径上的"序号"
- PosType seat; // 通道块在迷宫中的"坐标位置"
- int di; // 从此通道块走向下一通道块的"方向"(0~3表示东~北)
- };
- #include"c3-1.h" // 采用顺序栈存储结构
- #include"bo3-1.cpp" // 采用顺序栈的基本操作函数
- // 定义墙元素值为0,可通过路径为1,不能通过路径为-1,通过路径为足迹
- Status Pass(PosType b)
- { // 当迷宫m的b点的序号为1(可通过路径),返回OK;否则,返回ERROR
- if(m[b.x][b.y]==1)
- return OK;
- else
- return ERROR;
- }
- void FootPrint(PosType a)
- { // 使迷宫m的a点的值变为足迹(curstep)
- m[a.x][a.y]=curstep;
- }
- void NextPos(PosType &c,int di)
- { // 根据当前位置及移动方向,求得下一位置
- PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}}; // {行增量,列增量},移动方向,依次为东南西北
- c.x+=direc[di].x;
- c.y+=direc[di].y;
- }
- void MarkPrint(PosType b)
- { // 使迷宫m的b点的序号变为-1(不能通过的路径)
- m[b.x][b.y]=-1;
- }
- Status MazePath(PosType start,PosType end) // 算法3.3
- { // 若迷宫m中存在从入口start到出口end的通道,则求得一条
- // 存放在栈中(从栈底到栈顶),并返回TRUE;否则返回FALSE
- SqStack S; // 顺序栈
- PosType curpos; // 当前位置
- SElemType e; // 栈元素
- InitStack(S); // 初始化栈
- curpos=start; // 当前位置在入口
- do
- {
- if(Pass(curpos))
- { // 当前位置可以通过,即是未曾走到过的通道块
- FootPrint(curpos); // 留下足迹
- e.ord=curstep;
- e.seat=curpos;
- e.di=0;
- Push(S,e); // 入栈当前位置及状态
- curstep++; // 足迹加1
- if(curpos.x==end.x&&curpos.y==end.y) // 到达终点(出口)
- return TRUE;
- NextPos(curpos,e.di); // 由当前位置及移动方向,确定下一个当前位置
- }
- else
- { // 当前位置不能通过
- if(!StackEmpty(S)) // 栈不空
- {
- Pop(S,e); // 退栈到前一位置
- curstep--; // 足迹减1
- while(e.di==3&&!StackEmpty(S)) // 前一位置处于最后一个方向(北)
- {
- MarkPrint(e.seat); // 在前一位置留下不能通过的标记(-1)
- Pop(S,e); // 再退回一步
- curstep--; // 足迹再减1
- }
- if(e.di<3) // 没到最后一个方向(北)
- {
- e.di++; // 换下一个方向探索
- Push(S,e); // 入栈该位置的下一个方向
- curstep++; // 足迹加1
- curpos=e.seat; // 确定当前位置
- NextPos(curpos,e.di); // 确定下一个当前位置是该新方向上的相邻块
- }
- }
- }
- }while(!StackEmpty(S));
- return FALSE;
- }
- void main()
- {
- Init(1); // 初始化迷宫,通道值为1
- if(MazePath(begin,end)) // 有通路
- {
- printf("此迷宫从入口到出口的一条路径如下:/n");
- Print(); // 输出此通路
- }
- else
- printf("此迷宫没有从入口到出口的路径/n");
- }
- // algo3-6.cpp 表达式求值(输入的值在0~9之间,中间结果和输出的值在-128~127之间),算法3.4
- typedef char SElemType; // 栈元素为字符型
- #include"c1.h"
- #include"c3-1.h"
- #include"bo3-1.cpp"
- #include"func3-2.cpp"
- SElemType EvaluateExpression() // 算法3.4,有改动
- { // 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
- SqStack OPTR,OPND;
- SElemType a,b,c,x;
- InitStack(OPTR); // 初始化运算符栈OPTR和运算数栈OPND
- InitStack(OPND);
- Push(OPTR,'/n'); // 将换行符压入运算符栈OPTR的栈底(改)
- c=getchar(); // 由键盘读入1个字符到c
- GetTop(OPTR,x); // 将运算符栈OPTR的栈顶元素赋给x
- while(c!='/n'||x!='/n') // c和x不都是换行符
- {
- if(In(c)) // c是7种运算符之一
- switch(Precede(x,c)) // 判断x和c的优先权
- {
- case'<' :Push(OPTR,c); // 栈顶元素x的优先权低,入栈c
- c=getchar(); // 由键盘读入下一个字符到c
- break;
- case'=' :Pop(OPTR,x); // x='('且c=')'情况,弹出'('给x(后又扔掉)
- c=getchar(); // 由键盘读入下一个字符到c(扔掉')')
- break;
- case'>' :Pop(OPTR,x); // 栈顶元素x的优先权高,弹出运算符栈OPTR的栈顶元素给x(改)
- Pop(OPND,b); // 依次弹出运算数栈OPND的栈顶元素给b,a
- Pop(OPND,a);
- Push(OPND,Operate(a,x,b)); // 做运算a x b,并将运算结果入运算数栈
- }
- else if(c>='0'&&c<='9') // c是操作数
- {
- Push(OPND,c-48); // 将该操作数的值(不是ASCII码)压入运算数栈OPND
- c=getchar(); // 由键盘读入下一个字符到c
- }
- else // c是非法字符
- {
- printf("出现非法字符/n");
- exit(ERROR);
- }
- GetTop(OPTR,x); // 将运算符栈OPTR的栈顶元素赋给x
- }
- Pop(OPND,x); // 弹出运算数栈OPND的栈顶元素(运算结果)给x(改此处)
- if(!StackEmpty(OPND)) // 运算数栈OPND不空(运算符栈OPTR仅剩'/n')
- {
- printf("表达式不正确/n");
- exit(ERROR);
- }
- return x;
- }
- void main()
- {
- printf("请输入算术表达式(输入的值要在0~9之间、中间运算值和输出结果在-128~127之间)/n");
- printf("%d/n",EvaluateExpression()); // 返回值(8位2进制,1个字节)按整型格式输出
- }
- // algo3-7.cpp 表达式求值(范围为int类型,输入负数要用(0-正数)表示)
- typedef int SElemType; // 栈元素类型为整型,改algo3-6.cpp
- #include"c1.h"
- #include"c3-1.h" // 顺序栈的存储结构
- #include"bo3-1.cpp" // 顺序栈的基本操作
- #include"func3-2.cpp"
- SElemType EvaluateExpression()
- { // 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
- SqStack OPTR,OPND;
- SElemType a,b,d,x; // 改algo3-6.cpp
- char c; // 存放由键盘接收的字符,改algo3-6.cpp
- char z[11]; // 存放整数字符串,改algo3-6.cpp
- int i; // 改algo3-6.cpp
- InitStack(OPTR); // 初始化运算符栈OPTR和运算数栈OPND
- InitStack(OPND);
- Push(OPTR,'/n'); // 将换行符压入运算符栈OPTR的栈底(改)
- c=getchar(); // 由键盘读入1个字符到c
- GetTop(OPTR,x); // 将运算符栈OPTR的栈顶元素赋给x
- while(c!='/n'||x!='/n') // c和x不都是换行符
- {
- if(In(c)) // c是7种运算符之一
- switch(Precede(x,c)) // 判断x和c的优先权
- {
- case'<' :Push(OPTR,c); // 栈顶元素x的优先权低,入栈c
- c=getchar(); // 由键盘读入下一个字符到c
- break;
- case'=' :Pop(OPTR,x); // x='('且c=')'情况,弹出'('给x(后又扔掉)
- c=getchar(); // 由键盘读入下一个字符到c(扔掉')')
- break;
- case'>' :Pop(OPTR,x); // 栈顶元素x的优先权高,弹出运算符栈OPTR的栈顶元素给x(改)
- Pop(OPND,b); // 依次弹出运算数栈OPND的栈顶元素给b,a
- Pop(OPND,a);
- Push(OPND,Operate(a,x,b)); // 做运算a x b,并将运算结果入运算数栈
- }
- else if(c>='0'&&c<='9') // c是操作数,此语句改algo3-6.cpp
- {
- i=0;
- while(c>='0'&&c<='9') // 是连续数字
- {
- z[i++]=c;
- c=getchar();
- }
- z[i]=0; // 字符串结束符
- d=atoi(z); // 将z中保存的数值型字符串转为整型存于d
- Push(OPND,d); // 将d压入运算数栈OPND
- }
- else // c是非法字符,以下同algo3-6.cpp
- {
- printf("出现非法字符/n");
- exit(ERROR);
- }
- GetTop(OPTR,x); // 将运算符栈OPTR的栈顶元素赋给x
- }
- Pop(OPND,x); // 弹出运算数栈OPND的栈顶元素(运算结果)给x(改此处)
- if(!StackEmpty(OPND)) // 运算数栈OPND不空(运算符栈OPTR仅剩'/n')
- {
- printf("表达式不正确/n");
- exit(ERROR);
- }
- return x;
- }
- void main()
- {
- printf("请输入算术表达式,负数要用(0-正数)表示/n");
- printf("%d/n",EvaluateExpression());
- }
- // algo3-8.cpp 用递归调用求Ackerman(m,n)的值
- #include<stdio.h>
- int ack(int m,int n)
- {
- int z;
- if(m==0)
- z=n+1; // 出口
- else if(n==0)
- z=ack(m-1,1); // 对形参m降阶
- else
- z=ack(m-1,ack(m,n-1)); // 对形参m、n降阶
- return z;
- }
- void main()
- {
- int m,n;
- printf("Please input m,n:");
- scanf("%d,%d",&m,&n);
- printf("Ack(%d,%d)=%d/n",m,n,ack(m,n));
- }
- // algo3-10.cpp Hanoi塔问题,调用算法3.5的程序
- #include<stdio.h>
- int c=0; // 全局变量,搬动次数
- void move(char x,int n,char z)
- { // 第n个圆盘从塔座x搬到塔座z
- printf("第%i步: 将%i号盘从%c移到%c/n",++c,n,x,z);
- }
- void hanoi(int n,char x,char y,char z) // 算法3.5
- { // 将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘
- // 按规则搬到塔座z上。y可用作辅助塔座
- if(n==1) // (出口)
- move(x,1,z); // 将编号为1的圆盘从x移到z
- else
- {
- hanoi(n-1,x,z,y); // 将x上编号为1至n-1的圆盘移到y,z作辅助塔(降阶递归调用)
- move(x,n,z); // 将编号为n的圆盘从x移到z
- hanoi(n-1,y,x,z); // 将y上编号为1至n-1的圆盘移到z,x作辅助塔(降阶递归调用)
- }
- }
- void main()
- {
- int n;
- printf("3个塔座为a、b、c,圆盘最初在a座,借助b座移到c座。请输入圆盘数:");
- scanf("%d",&n);
- hanoi(n,'a','b','c');
- }
-
- // algo3-12.cpp 银行业务模拟。实现算法3.6、3.7的程序
- #define Qu 4 // 客户队列数
- #define Khjg 5 // 两相邻到达的客户的时间间隔最大值
- #define Blsj 30 // 每个客户办理业务的时间最大值
- #include"func3-3.cpp" // 包含algo3-12.cpp和algo3-13.cpp共同用到的函数和变量等
- LinkQueue q[Qu]; // Qu个客户队列
- QElemType customer; // 客户记录,临时变量
- //FILE *fq; // 文件型指针,用于指向a.txt文件
- void OpenForDay()
- { // 初始化事件链表ev且插入第1个到达事件,初始化Qu个队列
- int i;
- InitList(ev); // 初始化事件链表ev为空
- en.OccurTime=0; // 设定第1位客户到达时间为0(银行一开门,就有客户来)
- //fprintf(fq,"首位客户到达时刻=%3d,",en.OccurTime);
- en.NType=Qu; // 到达
- OrderInsert(ev,en,cmp); // 将第1个到达事件en有序插入事件表ev中,在bo2-6.cpp中
- for(i=0;i<Qu;++i) // 初始化Qu个队列
- InitQueue(q[i]);
- }
- int Minimum(LinkQueue Q[])
- { // 返回最短队列的序号,若有并列值,返回队列序号最小的
- int l[Qu];
- int i,k=0;
- for(i=0;i<Qu;i++)
- l[i]=QueueLength(Q[i]);
- for(i=1;i<Qu;i++)
- if(l[i]<l[0])
- {
- l[0]=l[i];
- k=i;
- }
- return k;
- }
- void CustomerArrived()
- { // 处理客户到达事件en(en.NType=Qu)
- QElemType f;
- int durtime,intertime,i;
- ++CustomerNum; // 客户数加1
- Random(durtime,intertime); // 生成当前客户办理业务的时间和下一个客户到达的时间间隔2个随机数
- et.OccurTime=en.OccurTime+intertime; // 下一客户et到达时刻=当前客户en的到达时间+时间间隔
- et.NType=Qu; // 下一客户到达事件
- i=Minimum(q); // 求长度最短队列的序号,等长为最小的序号(到达事件将入该队)
- //if(CustomerNum<=20) // 输出前20个客户到达信息到文件a.txt中
- // fprintf(fq,"办理业务的时间=%2d,所排队列=%d/n下一客户到达时刻=%3d,",durtime,i,et.OccurTime);
- if(et.OccurTime<CloseTime) // 下一客户到达时银行尚未关门
- OrderInsert(ev,et,cmp); // 按升序将下一客户到达事件et插入事件表ev中,在bo2-6.cpp中
- f.ArrivalTime=en.OccurTime; // 将当前客户到达事件en赋给队列元素f
- f.Duration=durtime;
- EnQueue(q[i],f); // 将f入队到第i队列(i=0~Qu-1)
- if(QueueLength(q[i])==1) // 该元素为队头元素
- {
- et.OccurTime=en.OccurTime+durtime; // 设定一个离开事件et
- et.NType=i;
- OrderInsert(ev,et,cmp); // 将此离开事件et按升序插入事件表ev中
- }
- }
- void CustomerDeparture()
- { // 处理客户离开事件en(en.NType<Qu)
- int i;
- i=en.NType; // 确定离开事件en发生的队列序号i
- DeQueue(q[i],customer); // 删除第i队列的排头客户
- TotalTime+=en.OccurTime-customer.ArrivalTime; // 客户逗留时间=离开事件en的发生时刻-该客户的到达时间
- if(!QueueEmpty(q[i]))
- { // 删除第i队列的排头客户后,第i队列仍不空
- GetHead(q[i],customer); // 将第i队列新的排头客户赋给customer
- et.OccurTime=en.OccurTime+customer.Duration; // 设定离开事件et,新排头的离开时间=原排头的离开时间+新排头办理业务的时间
- et.NType=i; // 第i个队列的离开事件
- OrderInsert(ev,et,cmp); // 将此离开事件et按升序插入事件表ev中
- }
- }
- void main()
- {
- //fq=fopen("a.txt","w"); // 打开a.txt文件,用于写入客户到达信息
- //fp=fopen("b.txt","w"); // 打开b.txt文件,用于写入有序事件表的历史记录
- printf("请输入银行营业时间长度(单位:分): ");
- scanf("%d",&CloseTime);
- //srand(time(0)); // 设置随机数种子,以使每次运行程序产生的随机数不同(time(0)是长整型数,与调用时间有关)
- Bank_Simulation();
- //fclose(fq); // 关闭a.txt
- //fclose(fp); // 关闭b.txt
- }
- #include"c1.h"
- #include"func3-1.cpp"
- #define D 8 // 移动方向数,只能取4和8。(8个,可斜行;4个,只可直走)
- typedef struct // 定义队列元素和栈元素为同类型的结构体
- {
- PosType seat; // 当前点的行值,列值
- int pre; // 前一点在队列中的序号
- }QElemType,SElemType; // 栈元素和队列元素
- #include"c3-1.h" // 栈的存储结构
- #include"bo3-1.cpp" // 栈的基本操作
- #include"c3-4.h" // 队列的存储结构
- #include"bo3-4.cpp" // 非循环顺序队列的基本操作(1)
- #include"bo3-9.cpp" // 非循环顺序队列的基本操作(2)
- struct // 移动数组,移动方向由正东起顺时针转
- {
- int x,y;
- }move[D]={
- #if D==8
- {0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
- #endif
- #if D==4
- {0,1},{1,0},{0,-1},{-1,0}};
- #endif
- void Path()
- { // 广度搜索法求一条迷宫路径
- SqQueue2 q; // 采用非循环顺序队列
- QElemType qf,qt; // 当前点和下一点
- SqStack s; // 采用顺序栈
- int i,flag=1; // 当找到出口,flag=0
- qf.seat.x=begin.x; // 将入口作为当前点
- qf.seat.y=begin.y;
- qf.pre=-1; // 设入口(第一点)的上一点的序号=-1
- m[qf.seat.x][qf.seat.y]=-1; // 初始点设为-1(标记已访问过)
- InitQueue(q);
- EnQueue(q,qf); // 起点入队
- while(!QueueEmpty(q)&&flag)
- { // 队列中还有没被广度搜索过的点且还没找到出口
- DeQueue(q,qf); // 出队qf为当前点
- for(i=0;i<D;i++) // 向各个方向尝试
- {
- qt.seat.x=qf.seat.x+move[i].x; // 下一点的坐标
- qt.seat.y=qf.seat.y+move[i].y;
- if(m[qt.seat.x][qt.seat.y]==1)
- { // 此点是通道且不曾被访问过
- m[qt.seat.x][qt.seat.y]=-1; // 标记已访问过
- qt.pre=q.front-1; // qt的前一点处于队列中现队头减1的位置(没删除)
- EnQueue(q,qt); // 入队qt
- if(qt.seat.x==end.x&&qt.seat.y==end.y) // 到达终点
- {
- flag=0;
- break;
- }
- }
- }
- }
- if(flag) // 搜索完整个队列还没到达终点
- printf("没有路径可到达终点!/n");
- else // 到达终点
- {
- InitStack(s); // 初始化s栈
- i=q.rear-1; // i为待入栈元素在队列中的位置
- while(i>=0) // 没到入口
- {
- Push(s,q.base[i]); // 将队列中的路径入栈(栈底为出口,栈顶为入口)
- i=q.base[i].pre; // i为前一元素在队列中的位置
- }
- i=0; // i为走出迷宫的足迹
- while(!StackEmpty(s))
- {
- Pop(s,qf); // 依照由入口到出口的顺序弹出路径
- i++;
- m[qf.seat.x][qf.seat.y]=i; // 标记路径为足迹(标记前的值为-1)
- }
- printf("走出迷宫的一个方案:/n");
- Print(); // 输出m数组
- }
- }
- void main()
- {
- Init(1); // 初始化迷宫,通道值为1
- Path(); // 求一条迷宫路径
- }
- // algo3-13.cpp 使用排队机的银行业务模拟
- #define Qu 4 // 窗口数
- #define Khjg 5 // 两相邻到达的客户的时间间隔最大值
- #define Blsj 30 // 每个客户办理业务的时间最大值
- #include"func3-3.cpp" // 包含algo3-12.cpp和algo3-13.cpp共同用到的函数和变量等
- LinkQueue q; // 排队机队列q
- QElemType customer[Qu]; // Qu个客户队列元素, 存放正在窗口办理业务的客户的信息
- //FILE *fq; // 文件型指针,用于指向c.txt文件
- //int j=0; // 计数器,产生c.txt文件用到
- Boolean chk[Qu]; // 窗口状态,1为闲,0为忙
- void OpenForDay()
- { // 初始化事件链表ev且插入第1个到达事件,初始化排队机q,初始化Qu个窗口为1(空闲)
- int i;
- InitList(ev); // 初始化事件链表ev为空
- en.OccurTime=0; // 设定第1位客户到达时间为0(银行一开门,就有客户来)
- en.NType=Qu; // 到达
- OrderInsert(ev,en,cmp); // 将第1个到达事件en有序插入事件表ev中,在bo2-6.cpp中
- InitQueue(q); // 初始化排队机队列q
- for(i=0;i<Qu;i++)
- chk[i]=1; // 初始化Qu个窗口为1(空闲)
- }
- int ChuangKou()
- { // 返回空闲窗口的序号(0~Qu-1),若有多个窗口空闲,返回序号最小的。若无空闲窗口,返回Qu
- int i;
- for(i=0;i<Qu;i++)
- if(chk[i])
- return i;
- return i;
- }
- void CustomerArrived()
- { // 处理客户到达事件en(en.NType=Qu),与algo3-12.cpp不同
- QElemType f;
- int durtime,intertime,i;
- ++CustomerNum; // 客户数加1
- Random(durtime,intertime); // 生成当前客户办理业务的时间和下一个客户到达的时间间隔2个随机数
- et.OccurTime=en.OccurTime+intertime; // 下一客户et到达时刻=当前客户en的到达时间+时间间隔
- et.NType=Qu; // 下一客户到达事件
- if(et.OccurTime<CloseTime) // 下一客户到达时银行尚未关门
- OrderInsert(ev,et,cmp); // 按升序将下一客户到达事件et插入事件表ev中,在bo2-6.cpp中
- f.ArrivalTime=en.OccurTime; // 将当前客户到达事件en赋给队列元素f
- f.Duration=durtime;
- EnQueue(q,f); // 将当前客户f入队到排队机
- i=ChuangKou(); // 求空闲窗口的序号
- if(i<Qu) // 有空闲窗口
- {
- DeQueue(q,customer[i]); // 删去排队机的排头客户(也就是刚入队的f由排队机到i号窗口)
- // if(j++<20) // 输出前20个客户到达信息及处理业务窗口信息到文件c.txt中
- // fprintf(fq,"客户到达时刻=%3d,办理业务的时间=%2d,所在窗口=%d/n",customer[i].ArrivalTime,customer[i].Duration,i);
- et.OccurTime=en.OccurTime+customer[i].Duration; // 设定一个i号窗口的离开事件et
- et.NType=i; // 第i号窗口的离开事件
- OrderInsert(ev,et,cmp); // 将此离开事件et按升序插入事件表ev中
- chk[i]=0; // i号窗口状态变忙
- }
- }
- void CustomerDeparture()
- { // 处理客户离开事件en(en.NType<Qu),与algo3-12.cpp不同
- int i;
- i=en.NType; // 确定离开事件en发生的窗口序号i
- chk[i]=1; // i号窗口状态变闲
- TotalTime+=en.OccurTime-customer[i].ArrivalTime; // 客户逗留时间=离开事件en的发生时刻-该客户的到达时间
- if(!QueueEmpty(q))
- { // 第i窗口的客户离开后,排队机仍不空
- DeQueue(q,customer[i]); // 删去排队机的排头客户并将其赋给customer[i](排队机的排头客户去i窗口办理业务)
- // if(j++<20) // 输出前20个客户到达信息及处理业务窗口信息到文件c.txt中
- // fprintf(fq,"客户到达时刻=%3d,办理业务的时间=%2d,所在窗口=%d/n",customer[i].ArrivalTime,customer[i].Duration,i);
- chk[i]=0; // i号窗口状态变忙
- et.OccurTime=en.OccurTime+customer[i].Duration; // 设定customer[i]的离开事件et,客户的离开时间=原客户的离开时间+当前客户办理业务的时间
- et.NType=i; // 第i号窗口的离开事件
- OrderInsert(ev,et,cmp); // 将此离开事件et按升序插入事件表ev中
- }
- }
- void main()
- {
- //fq=fopen("c.txt","w"); // 打开c.txt文件,用于写入客户到达信息
- //fp=fopen("d.txt","w"); // 打开d.txt文件,用于写入有序事件表的历史记录
- printf("请输入银行营业时间长度(单位:分): ");
- scanf("%d",&CloseTime);
- //srand(time(0)); // 设置随机数种子,以使每次运行程序产生的随机数不同(time(0)是长整型数,与调用时间有关)
- Bank_Simulation();
- //fclose(fq); // 关闭c.txt
- //fclose(fp); // 关闭d.txt
- }