algo3-01~3-13.cpp 栈和队列主程序

  1.  // algo3-9.cpp 用递归函数求解迷宫问题(求出所有解)
  2.  #include"c1.h" // 根据《PASCAL程序设计》(郑启华编著)中的程序改编
  3.  #include"func3-1.cpp" // 定义墙元素值为0,可通过路径为-1,通过路径为足迹
  4.  void Try(PosType cur,int curstep)
  5.  { // 由当前位置cur、当前步骤curstep试探下一点
  6.    int i;
  7.    PosType next; // 下一个位置
  8.    PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}}; // {行增量,列增量},移动方向,依次为东南西北
  9.    for(i=0;i<=3;i++) // 依次试探东南西北四个方向
  10.    {
  11.      next.x=cur.x+direc[i].x; // 根据移动方向,给下一位置赋值
  12.      next.y=cur.y+direc[i].y;
  13.      if(m[next.x][next.y]==-1) // 下一个位置是通路
  14.      {
  15.        m[next.x][next.y]=++curstep; // 将下一个位置设为足迹
  16.        if(next.x!=end.x||next.y!=end.y) // 没到终点
  17.          Try(next,curstep); // 由下一个位置继续试探(降阶递归调用,离终点更近)
  18.        else // 到终点
  19.        {
  20.          Print(); // 输出结果(出口,不再递归调用)
  21.          printf("/n");
  22.        }
  23.        m[next.x][next.y]=-1; // 恢复为通路,以便在另一个方向试探另一条路
  24.        curstep--; // 足迹也减1
  25.      }
  26.    }
  27.  }
  28.  void main()
  29.  {
  30.    Init(-1); // 初始化迷宫,通道值为-1
  31.    printf("此迷宫从入口到出口的路径如下:/n");
  32.    m[begin.x][begin.y]=1; // 入口的足迹为1
  33.    Try(begin,1); // 由第1步入口试探起
  34.  }
 
  1.  // algo3-1.cpp 调用算法3.1的程序
  2.  #define N 8 // 定义待转换的进制N(2~9)
  3.  typedef int SElemType; // 定义栈元素类型为整型
  4.  #include"c1.h"
  5.  #include"c3-1.h" // 采用顺序栈
  6.  #include"bo3-1.cpp" // 利用顺序栈的基本操作
  7.  void conversion() // 算法3.1
  8.  { // 对于输入的任意一个非负10进制整数,打印输出与其等值的N进制数
  9.    SqStack s;
  10.    unsigned n; // 非负整数
  11.    SElemType e;
  12.    InitStack(s); // 初始化栈
  13.    printf("将10进制整数n转换为%d进制数,请输入:n(>=0)=",N);
  14.    scanf("%u",&n); // 输入非负十进制整数n
  15.    while(n) // 当n不等于0
  16.    {
  17.      Push(s,n%N); // 入栈n除以N的余数(N进制的低位)
  18.      n=n/N;
  19.    }
  20.    while(!StackEmpty(s)) // 当栈不空
  21.    {
  22.      Pop(s,e); // 弹出栈顶元素且赋值给e
  23.      printf("%d",e); // 输出e
  24.    }
  25.    printf("/n");
  26.  }
  27.  void main()
  28.  {
  29.    conversion();
  30.  }

 

  1.  // algo3-2.cpp 改算法3.1,10进制→16进制
  2.  typedef int SElemType; // 定义栈元素类型为整型
  3.  #include"c1.h"
  4.  #include"c3-1.h" // 采用顺序栈
  5.  #include"bo3-1.cpp" // 利用顺序栈的基本操作
  6.  void conversion()
  7.  { // 对于输入的任意一个非负10进制整数,打印输出与其等值的16进制数
  8.    SqStack s;
  9.    unsigned n; // 非负整数
  10.    SElemType e;
  11.    InitStack(s); // 初始化栈
  12.    printf("将10进制整数n转换为16进制数,请输入:n(>=0)=");
  13.    scanf("%u",&n); // 输入非负十进制整数n
  14.    while(n) // 当n不等于0
  15.    {
  16.      Push(s,n%16); // 入栈n除以16的余数(16进制的低位)
  17.      n=n/16;
  18.    }
  19.    while(!StackEmpty(s)) // 当栈不空
  20.    {
  21.      Pop(s,e); // 弹出栈顶元素且赋值给e
  22.      if(e<=9)
  23.        printf("%d",e);
  24.      else
  25.        printf("%c",e+55); // 大于9的余数,输出相应的字符
  26.    }
  27.    printf("/n");
  28.  }
  29.  void main()
  30.  {
  31.    conversion();
  32.  }
  1.  // algo3-4.cpp 行编辑程序,实现算法3.2
  2.  typedef char SElemType;
  3.  #include"c1.h"
  4.  #include"c3-1.h"
  5.  #include"bo3-1.cpp"
  6.  FILE *fp;
  7.  void copy(SElemType c)
  8.  { // 将字符c送至fp所指的文件中
  9.    fputc(c,fp);
  10.  }
  11.  void LineEdit()
  12.  { // 利用字符栈s,从终端接收一行并送至调用过程的数据区。算法3.2
  13.    SqStack s;
  14.    char ch;
  15.    InitStack(s);
  16.    printf("请输入一个文本文件,^Z结束输入:/n");
  17.    ch=getchar();
  18.    while(ch!=EOF)
  19.    { // 当全文没结束(EOF为^Z键,全文结束符)
  20.      while(ch!=EOF&&ch!='/n')
  21.      { // 当全文没结束且没到行末(不是换行符)
  22.        switch(ch)
  23.        {
  24.          case '#':if(!StackEmpty(s))
  25.                     Pop(s,ch); // 仅当栈非空时退栈,c可由ch替代
  26.                   break;
  27.          case '@':ClearStack(s); // 重置s为空栈
  28.                   break;
  29.          default :Push(s,ch); // 其他字符进栈
  30.        }
  31.        ch=getchar(); // 从终端接收下一个字符
  32.      }
  33.      StackTraverse(s,copy); // 将从栈底到栈顶的栈内字符传送至文件
  34.      fputc('/n',fp); // 向文件输入一个换行符
  35.      ClearStack(s); // 重置s为空栈
  36.      if(ch!=EOF)
  37.        ch=getchar();
  38.    }
  39.    DestroyStack(s);
  40.  }
  41.  void main()
  42.  {
  43.    fp=fopen("ed.txt","w"); // 在当前目录下建立ed.txt文件,用于写数据,
  44.    if(fp)                  // 如已有同名文件则先删除原文件
  45.    {
  46.      LineEdit();
  47.      fclose(fp); // 关闭fp所指的文件
  48.    }
  49.    else
  50.      printf("建立文件失败!/n");
  51.  }

 

 

  1.  // algo3-3.cpp 括号(()、[]和{})匹配的检验
  2.  typedef char SElemType;
  3.  #include"c1.h"
  4.  #include"c3-1.h"
  5.  #include"bo3-1.cpp"
  6.  void check()
  7.  { // 对于输入的任意一个字符串,检验括号是否配对
  8.    SqStack s;
  9.    SElemType ch[80],*p,e;
  10.    InitStack(s); // 初始化栈
  11.    printf("请输入带括号(()、[]和{})的表达式/n");
  12.    gets(ch);
  13.    p=ch; // p指向字符串的首字符
  14.    while(*p) // 没到串尾
  15.      switch(*p)
  16.      {
  17.        case '(':
  18.        case '[':
  19.        case '{':Push(s,*p++); // 左括号入栈,且p++
  20.                 break;
  21.        case ')':
  22.        case ']':
  23.        case '}':if(!StackEmpty(s)) // 栈不空
  24.                 {
  25.                   Pop(s,e); // 弹出栈顶元素
  26.                   if(!(e=='('&&*p==')'||e=='['&&*p==']'||e=='{'&&*p=='}'))
  27.                   { // 出现3种匹配情况之外的情况
  28.                     printf("左右括号不配对/n");
  29.                     exit(ERROR);
  30.                   }
  31.                 }
  32.                 else // 栈空
  33.                 {
  34.                   printf("缺乏左括号/n");
  35.                   exit(ERROR);
  36.                 }
  37.        default: p++; // 其它字符不处理,指针向后移
  38.      }
  39.    if(StackEmpty(s)) // 字符串结束时栈空
  40.      printf("括号匹配/n");
  41.    else
  42.      printf("缺乏右括号/n");
  43.  }
  44.  void main()
  45.  {
  46.    check();
  47.  }
  1.  // algo3-5.cpp 利用栈求解迷宫问题(只输出一个解,算法3.3)
  2.  #include"c1.h"
  3.  #include"func3-1.cpp"
  4.  int curstep=1; // 当前足迹,初值(在入口处)为1
  5.  struct SElemType // 栈的元素类型
  6.  {
  7.    int ord; // 通道块在路径上的"序号"
  8.    PosType seat; // 通道块在迷宫中的"坐标位置"
  9.    int di; // 从此通道块走向下一通道块的"方向"(0~3表示东~北)
  10.  };
  11.  #include"c3-1.h" // 采用顺序栈存储结构
  12.  #include"bo3-1.cpp" // 采用顺序栈的基本操作函数
  13.  // 定义墙元素值为0,可通过路径为1,不能通过路径为-1,通过路径为足迹
  14.  Status Pass(PosType b)
  15.  { // 当迷宫m的b点的序号为1(可通过路径),返回OK;否则,返回ERROR
  16.    if(m[b.x][b.y]==1)
  17.      return OK;
  18.    else
  19.      return ERROR;
  20.  }
  21.  void FootPrint(PosType a)
  22.  { // 使迷宫m的a点的值变为足迹(curstep)
  23.    m[a.x][a.y]=curstep;
  24.  }
  25.  void NextPos(PosType &c,int di)
  26.  { // 根据当前位置及移动方向,求得下一位置
  27.    PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}}; // {行增量,列增量},移动方向,依次为东南西北
  28.    c.x+=direc[di].x;
  29.    c.y+=direc[di].y;
  30.  }
  31.  void MarkPrint(PosType b)
  32.  { // 使迷宫m的b点的序号变为-1(不能通过的路径)
  33.    m[b.x][b.y]=-1;
  34.  }
  35.  Status MazePath(PosType start,PosType end) // 算法3.3
  36.  { // 若迷宫m中存在从入口start到出口end的通道,则求得一条
  37.    // 存放在栈中(从栈底到栈顶),并返回TRUE;否则返回FALSE
  38.    SqStack S; // 顺序栈
  39.    PosType curpos; // 当前位置
  40.    SElemType e; // 栈元素
  41.    InitStack(S); // 初始化栈
  42.    curpos=start; // 当前位置在入口
  43.    do
  44.    {
  45.      if(Pass(curpos))
  46.      { // 当前位置可以通过,即是未曾走到过的通道块
  47.        FootPrint(curpos); // 留下足迹
  48.        e.ord=curstep;
  49.        e.seat=curpos;
  50.        e.di=0;
  51.        Push(S,e); // 入栈当前位置及状态
  52.        curstep++; // 足迹加1
  53.        if(curpos.x==end.x&&curpos.y==end.y) // 到达终点(出口)
  54.          return TRUE;
  55.        NextPos(curpos,e.di); // 由当前位置及移动方向,确定下一个当前位置
  56.      }
  57.      else
  58.      { // 当前位置不能通过
  59.        if(!StackEmpty(S)) // 栈不空
  60.        {
  61.          Pop(S,e); // 退栈到前一位置
  62.          curstep--; // 足迹减1
  63.          while(e.di==3&&!StackEmpty(S)) // 前一位置处于最后一个方向(北)
  64.          {
  65.            MarkPrint(e.seat); // 在前一位置留下不能通过的标记(-1)
  66.            Pop(S,e); // 再退回一步
  67.            curstep--; // 足迹再减1
  68.          }
  69.          if(e.di<3) // 没到最后一个方向(北)
  70.          {
  71.            e.di++; // 换下一个方向探索
  72.            Push(S,e); // 入栈该位置的下一个方向
  73.            curstep++; // 足迹加1
  74.            curpos=e.seat; // 确定当前位置
  75.            NextPos(curpos,e.di); // 确定下一个当前位置是该新方向上的相邻块
  76.          }
  77.        }
  78.      }
  79.    }while(!StackEmpty(S));
  80.    return FALSE;
  81.  }
  82.  void main()
  83.  {
  84.    Init(1); // 初始化迷宫,通道值为1
  85.    if(MazePath(begin,end)) // 有通路
  86.    {
  87.      printf("此迷宫从入口到出口的一条路径如下:/n");
  88.      Print(); // 输出此通路
  89.    }
  90.    else
  91.      printf("此迷宫没有从入口到出口的路径/n");
  92.  }

 

  1.  // algo3-6.cpp 表达式求值(输入的值在0~9之间,中间结果和输出的值在-128~127之间),算法3.4
  2.  typedef char SElemType; // 栈元素为字符型
  3.  #include"c1.h"
  4.  #include"c3-1.h"
  5.  #include"bo3-1.cpp"
  6.  #include"func3-2.cpp"
  7.  SElemType EvaluateExpression() // 算法3.4,有改动
  8.  { // 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
  9.    SqStack OPTR,OPND;
  10.    SElemType a,b,c,x;
  11.    InitStack(OPTR); // 初始化运算符栈OPTR和运算数栈OPND
  12.    InitStack(OPND);
  13.    Push(OPTR,'/n'); // 将换行符压入运算符栈OPTR的栈底(改)
  14.    c=getchar(); // 由键盘读入1个字符到c
  15.    GetTop(OPTR,x); // 将运算符栈OPTR的栈顶元素赋给x
  16.    while(c!='/n'||x!='/n'// c和x不都是换行符
  17.    {
  18.      if(In(c)) // c是7种运算符之一
  19.        switch(Precede(x,c)) // 判断x和c的优先权
  20.        {
  21.          case'<' :Push(OPTR,c); // 栈顶元素x的优先权低,入栈c
  22.                   c=getchar();  // 由键盘读入下一个字符到c
  23.                   break;
  24.          case'=' :Pop(OPTR,x); // x='('且c=')'情况,弹出'('给x(后又扔掉)
  25.                   c=getchar(); // 由键盘读入下一个字符到c(扔掉')')
  26.                   break;
  27.          case'>' :Pop(OPTR,x); // 栈顶元素x的优先权高,弹出运算符栈OPTR的栈顶元素给x(改)
  28.                   Pop(OPND,b); // 依次弹出运算数栈OPND的栈顶元素给b,a
  29.                   Pop(OPND,a);
  30.                   Push(OPND,Operate(a,x,b)); // 做运算a x b,并将运算结果入运算数栈
  31.        }
  32.      else if(c>='0'&&c<='9'// c是操作数
  33.      {
  34.        Push(OPND,c-48); // 将该操作数的值(不是ASCII码)压入运算数栈OPND
  35.        c=getchar(); // 由键盘读入下一个字符到c
  36.      }
  37.      else // c是非法字符
  38.      {
  39.        printf("出现非法字符/n");
  40.        exit(ERROR);
  41.      }
  42.      GetTop(OPTR,x); // 将运算符栈OPTR的栈顶元素赋给x
  43.    }
  44.    Pop(OPND,x); // 弹出运算数栈OPND的栈顶元素(运算结果)给x(改此处)
  45.    if(!StackEmpty(OPND)) // 运算数栈OPND不空(运算符栈OPTR仅剩'/n')
  46.    {
  47.      printf("表达式不正确/n");
  48.      exit(ERROR);
  49.    }
  50.    return x;
  51.  }
  52.  void main()
  53.  {
  54.    printf("请输入算术表达式(输入的值要在0~9之间、中间运算值和输出结果在-128~127之间)/n");
  55.    printf("%d/n",EvaluateExpression()); // 返回值(8位2进制,1个字节)按整型格式输出
  56.  }
  1.  // algo3-7.cpp 表达式求值(范围为int类型,输入负数要用(0-正数)表示)
  2.  typedef int SElemType; // 栈元素类型为整型,改algo3-6.cpp
  3.  #include"c1.h"
  4.  #include"c3-1.h" // 顺序栈的存储结构
  5.  #include"bo3-1.cpp" // 顺序栈的基本操作
  6.  #include"func3-2.cpp"
  7.  SElemType EvaluateExpression()
  8.  { // 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
  9.    SqStack OPTR,OPND;
  10.    SElemType a,b,d,x; // 改algo3-6.cpp
  11.    char c; // 存放由键盘接收的字符,改algo3-6.cpp
  12.    char z[11]; // 存放整数字符串,改algo3-6.cpp
  13.    int i; // 改algo3-6.cpp
  14.    InitStack(OPTR); // 初始化运算符栈OPTR和运算数栈OPND
  15.    InitStack(OPND);
  16.    Push(OPTR,'/n'); // 将换行符压入运算符栈OPTR的栈底(改)
  17.    c=getchar(); // 由键盘读入1个字符到c
  18.    GetTop(OPTR,x); // 将运算符栈OPTR的栈顶元素赋给x
  19.    while(c!='/n'||x!='/n'// c和x不都是换行符
  20.    {
  21.      if(In(c)) // c是7种运算符之一
  22.        switch(Precede(x,c)) // 判断x和c的优先权
  23.        {
  24.          case'<' :Push(OPTR,c); // 栈顶元素x的优先权低,入栈c
  25.                   c=getchar();  // 由键盘读入下一个字符到c
  26.                   break;
  27.          case'=' :Pop(OPTR,x); // x='('且c=')'情况,弹出'('给x(后又扔掉)
  28.                   c=getchar(); // 由键盘读入下一个字符到c(扔掉')')
  29.                   break;
  30.          case'>' :Pop(OPTR,x); // 栈顶元素x的优先权高,弹出运算符栈OPTR的栈顶元素给x(改)
  31.                   Pop(OPND,b); // 依次弹出运算数栈OPND的栈顶元素给b,a
  32.                   Pop(OPND,a);
  33.                   Push(OPND,Operate(a,x,b)); // 做运算a x b,并将运算结果入运算数栈
  34.        }
  35.      else if(c>='0'&&c<='9'// c是操作数,此语句改algo3-6.cpp
  36.      {
  37.        i=0;
  38.        while(c>='0'&&c<='9'// 是连续数字
  39.        {
  40.          z[i++]=c;
  41.          c=getchar();
  42.        }
  43.        z[i]=0; // 字符串结束符
  44.        d=atoi(z); // 将z中保存的数值型字符串转为整型存于d
  45.        Push(OPND,d); // 将d压入运算数栈OPND
  46.      }
  47.      else // c是非法字符,以下同algo3-6.cpp
  48.      {
  49.        printf("出现非法字符/n");
  50.        exit(ERROR);
  51.      }
  52.      GetTop(OPTR,x); // 将运算符栈OPTR的栈顶元素赋给x
  53.    }
  54.    Pop(OPND,x); // 弹出运算数栈OPND的栈顶元素(运算结果)给x(改此处)
  55.    if(!StackEmpty(OPND)) // 运算数栈OPND不空(运算符栈OPTR仅剩'/n')
  56.    {
  57.      printf("表达式不正确/n");
  58.      exit(ERROR);
  59.    }
  60.    return x;
  61.  }
  62.  void main()
  63.  {
  64.    printf("请输入算术表达式,负数要用(0-正数)表示/n");
  65.    printf("%d/n",EvaluateExpression());
  66.  }
  1.  // algo3-8.cpp 用递归调用求Ackerman(m,n)的值
  2.  #include<stdio.h>
  3.  int ack(int m,int n)
  4.  {
  5.    int z;
  6.    if(m==0)
  7.      z=n+1; // 出口
  8.    else if(n==0)
  9.      z=ack(m-1,1); // 对形参m降阶
  10.    else
  11.      z=ack(m-1,ack(m,n-1)); // 对形参m、n降阶
  12.    return z;
  13.  }
  14.  void main()
  15.  {
  16.    int m,n;
  17.    printf("Please input m,n:");
  18.    scanf("%d,%d",&m,&n);
  19.    printf("Ack(%d,%d)=%d/n",m,n,ack(m,n));
  20.  }
  1.  // algo3-10.cpp Hanoi塔问题,调用算法3.5的程序
  2.  #include<stdio.h>
  3.  int c=0; // 全局变量,搬动次数
  4.  void move(char x,int n,char z)
  5.  { // 第n个圆盘从塔座x搬到塔座z
  6.    printf("第%i步: 将%i号盘从%c移到%c/n",++c,n,x,z);
  7.  }
  8.  void hanoi(int n,char x,char y,char z) // 算法3.5
  9.  { // 将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘
  10.    // 按规则搬到塔座z上。y可用作辅助塔座
  11.    if(n==1) // (出口)
  12.      move(x,1,z); // 将编号为1的圆盘从x移到z
  13.    else
  14.    {
  15.      hanoi(n-1,x,z,y); // 将x上编号为1至n-1的圆盘移到y,z作辅助塔(降阶递归调用)
  16.      move(x,n,z); // 将编号为n的圆盘从x移到z
  17.      hanoi(n-1,y,x,z); // 将y上编号为1至n-1的圆盘移到z,x作辅助塔(降阶递归调用)
  18.    }
  19.  }
  20.  void main()
  21.  {
  22.    int n;
  23.    printf("3个塔座为a、b、c,圆盘最初在a座,借助b座移到c座。请输入圆盘数:");
  24.    scanf("%d",&n);
  25.    hanoi(n,'a','b','c');
  26.  }

 

 

    1.  // algo3-12.cpp 银行业务模拟。实现算法3.6、3.7的程序
    2.  #define Qu 4 // 客户队列数
    3.  #define Khjg 5 // 两相邻到达的客户的时间间隔最大值
    4.  #define Blsj 30 // 每个客户办理业务的时间最大值
    5.  #include"func3-3.cpp" // 包含algo3-12.cpp和algo3-13.cpp共同用到的函数和变量等
    6.  LinkQueue q[Qu]; // Qu个客户队列
    7.  QElemType customer; // 客户记录,临时变量
    8.  //FILE *fq; // 文件型指针,用于指向a.txt文件
    9.  void OpenForDay()
    10.  { // 初始化事件链表ev且插入第1个到达事件,初始化Qu个队列
    11.    int i;
    12.    InitList(ev); // 初始化事件链表ev为空
    13.    en.OccurTime=0; // 设定第1位客户到达时间为0(银行一开门,就有客户来)
    14.  //fprintf(fq,"首位客户到达时刻=%3d,",en.OccurTime);
    15.    en.NType=Qu; // 到达
    16.    OrderInsert(ev,en,cmp); // 将第1个到达事件en有序插入事件表ev中,在bo2-6.cpp中
    17.    for(i=0;i<Qu;++i) // 初始化Qu个队列
    18.      InitQueue(q[i]);
    19.  }
    20.  int Minimum(LinkQueue Q[])
    21.  { // 返回最短队列的序号,若有并列值,返回队列序号最小的
    22.    int l[Qu];
    23.    int i,k=0;
    24.    for(i=0;i<Qu;i++)
    25.      l[i]=QueueLength(Q[i]);
    26.    for(i=1;i<Qu;i++)
    27.      if(l[i]<l[0])
    28.      {
    29.        l[0]=l[i];
    30.        k=i;
    31.      }
    32.    return k;
    33.  }
    34.  void CustomerArrived()
    35.  { // 处理客户到达事件en(en.NType=Qu)
    36.    QElemType f;
    37.    int durtime,intertime,i;
    38.    ++CustomerNum; // 客户数加1
    39.    Random(durtime,intertime); // 生成当前客户办理业务的时间和下一个客户到达的时间间隔2个随机数
    40.    et.OccurTime=en.OccurTime+intertime; // 下一客户et到达时刻=当前客户en的到达时间+时间间隔
    41.    et.NType=Qu; // 下一客户到达事件
    42.    i=Minimum(q); // 求长度最短队列的序号,等长为最小的序号(到达事件将入该队)
    43.  //if(CustomerNum<=20) // 输出前20个客户到达信息到文件a.txt中
    44.  //  fprintf(fq,"办理业务的时间=%2d,所排队列=%d/n下一客户到达时刻=%3d,",durtime,i,et.OccurTime);
    45.    if(et.OccurTime<CloseTime) // 下一客户到达时银行尚未关门
    46.      OrderInsert(ev,et,cmp); // 按升序将下一客户到达事件et插入事件表ev中,在bo2-6.cpp中
    47.    f.ArrivalTime=en.OccurTime; // 将当前客户到达事件en赋给队列元素f
    48.    f.Duration=durtime;
    49.    EnQueue(q[i],f); // 将f入队到第i队列(i=0~Qu-1)
    50.    if(QueueLength(q[i])==1) // 该元素为队头元素
    51.    {
    52.      et.OccurTime=en.OccurTime+durtime; // 设定一个离开事件et
    53.      et.NType=i;
    54.      OrderInsert(ev,et,cmp); // 将此离开事件et按升序插入事件表ev中
    55.    }
    56.  }
    57.  void CustomerDeparture()
    58.  { // 处理客户离开事件en(en.NType<Qu)
    59.    int i;
    60.    i=en.NType; // 确定离开事件en发生的队列序号i
    61.    DeQueue(q[i],customer); // 删除第i队列的排头客户
    62.    TotalTime+=en.OccurTime-customer.ArrivalTime; // 客户逗留时间=离开事件en的发生时刻-该客户的到达时间
    63.    if(!QueueEmpty(q[i]))
    64.    { // 删除第i队列的排头客户后,第i队列仍不空
    65.      GetHead(q[i],customer); // 将第i队列新的排头客户赋给customer
    66.      et.OccurTime=en.OccurTime+customer.Duration; // 设定离开事件et,新排头的离开时间=原排头的离开时间+新排头办理业务的时间
    67.      et.NType=i; // 第i个队列的离开事件
    68.      OrderInsert(ev,et,cmp); // 将此离开事件et按升序插入事件表ev中
    69.    }
    70.  }
    71.  void main()
    72.  {
    73.  //fq=fopen("a.txt","w"); // 打开a.txt文件,用于写入客户到达信息
    74.  //fp=fopen("b.txt","w"); // 打开b.txt文件,用于写入有序事件表的历史记录
    75.    printf("请输入银行营业时间长度(单位:分): ");
    76.    scanf("%d",&CloseTime);
    77.  //srand(time(0)); // 设置随机数种子,以使每次运行程序产生的随机数不同(time(0)是长整型数,与调用时间有关)
    78.    Bank_Simulation();
    79.  //fclose(fq); // 关闭a.txt
    80.  //fclose(fp); // 关闭b.txt
    81.  }
     // algo3-11.cpp 利用非循环顺序队列采用广度搜索法求解迷宫问题(一条路径)
  1.  #include"c1.h"
  2.  #include"func3-1.cpp"
  3.  #define D 8 // 移动方向数,只能取4和8。(8个,可斜行;4个,只可直走)
  4.  typedef struct // 定义队列元素和栈元素为同类型的结构体
  5.  {
  6.    PosType seat; // 当前点的行值,列值
  7.    int pre; // 前一点在队列中的序号
  8.  }QElemType,SElemType; // 栈元素和队列元素
  9.  #include"c3-1.h" // 栈的存储结构
  10.  #include"bo3-1.cpp" // 栈的基本操作
  11.  #include"c3-4.h" // 队列的存储结构
  12.  #include"bo3-4.cpp" // 非循环顺序队列的基本操作(1)
  13.  #include"bo3-9.cpp" // 非循环顺序队列的基本操作(2)
  14.  struct // 移动数组,移动方向由正东起顺时针转
  15.  {
  16.    int x,y;
  17.  }move[D]={
  18.  #if D==8
  19.        {0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
  20.  #endif
  21.  #if D==4
  22.        {0,1},{1,0},{0,-1},{-1,0}};
  23.  #endif
  24.  void Path()
  25.  { // 广度搜索法求一条迷宫路径
  26.    SqQueue2 q; // 采用非循环顺序队列
  27.    QElemType qf,qt; // 当前点和下一点
  28.    SqStack s; // 采用顺序栈
  29.    int i,flag=1; // 当找到出口,flag=0
  30.    qf.seat.x=begin.x; // 将入口作为当前点
  31.    qf.seat.y=begin.y;
  32.    qf.pre=-1; // 设入口(第一点)的上一点的序号=-1
  33.    m[qf.seat.x][qf.seat.y]=-1; // 初始点设为-1(标记已访问过)
  34.    InitQueue(q);
  35.    EnQueue(q,qf); // 起点入队
  36.    while(!QueueEmpty(q)&&flag)
  37.    { // 队列中还有没被广度搜索过的点且还没找到出口
  38.      DeQueue(q,qf); // 出队qf为当前点
  39.      for(i=0;i<D;i++) // 向各个方向尝试
  40.      {
  41.        qt.seat.x=qf.seat.x+move[i].x; // 下一点的坐标
  42.        qt.seat.y=qf.seat.y+move[i].y;
  43.        if(m[qt.seat.x][qt.seat.y]==1)
  44.        { // 此点是通道且不曾被访问过
  45.          m[qt.seat.x][qt.seat.y]=-1; // 标记已访问过
  46.          qt.pre=q.front-1; // qt的前一点处于队列中现队头减1的位置(没删除)
  47.          EnQueue(q,qt); // 入队qt
  48.          if(qt.seat.x==end.x&&qt.seat.y==end.y) // 到达终点
  49.          {
  50.            flag=0;
  51.            break;
  52.          }
  53.        }
  54.      }
  55.    }
  56.    if(flag) // 搜索完整个队列还没到达终点
  57.      printf("没有路径可到达终点!/n");
  58.    else // 到达终点
  59.    {
  60.      InitStack(s); // 初始化s栈
  61.      i=q.rear-1; // i为待入栈元素在队列中的位置
  62.      while(i>=0) // 没到入口
  63.      {
  64.        Push(s,q.base[i]); // 将队列中的路径入栈(栈底为出口,栈顶为入口)
  65.        i=q.base[i].pre; // i为前一元素在队列中的位置
  66.      }
  67.      i=0; // i为走出迷宫的足迹
  68.      while(!StackEmpty(s))
  69.      {
  70.        Pop(s,qf); // 依照由入口到出口的顺序弹出路径
  71.        i++;
  72.        m[qf.seat.x][qf.seat.y]=i; // 标记路径为足迹(标记前的值为-1)
  73.      }
  74.      printf("走出迷宫的一个方案:/n");
  75.      Print(); // 输出m数组
  76.    }
  77.  }
  78.  void main()
  79.  {
  80.    Init(1); // 初始化迷宫,通道值为1
  81.    Path(); // 求一条迷宫路径
  82.  }
  1.  // algo3-13.cpp 使用排队机的银行业务模拟
  2.  #define Qu 4 // 窗口数
  3.  #define Khjg 5 // 两相邻到达的客户的时间间隔最大值
  4.  #define Blsj 30 // 每个客户办理业务的时间最大值
  5.  #include"func3-3.cpp" // 包含algo3-12.cpp和algo3-13.cpp共同用到的函数和变量等
  6.  LinkQueue q; // 排队机队列q
  7.  QElemType customer[Qu]; // Qu个客户队列元素, 存放正在窗口办理业务的客户的信息
  8.  //FILE *fq; // 文件型指针,用于指向c.txt文件
  9.  //int j=0; // 计数器,产生c.txt文件用到
  10.  Boolean chk[Qu]; // 窗口状态,1为闲,0为忙
  11.  void OpenForDay()
  12.  { // 初始化事件链表ev且插入第1个到达事件,初始化排队机q,初始化Qu个窗口为1(空闲)
  13.    int i;
  14.    InitList(ev); // 初始化事件链表ev为空
  15.    en.OccurTime=0; // 设定第1位客户到达时间为0(银行一开门,就有客户来)
  16.    en.NType=Qu; // 到达
  17.    OrderInsert(ev,en,cmp); // 将第1个到达事件en有序插入事件表ev中,在bo2-6.cpp中
  18.    InitQueue(q); // 初始化排队机队列q
  19.    for(i=0;i<Qu;i++)
  20.      chk[i]=1; // 初始化Qu个窗口为1(空闲)
  21.  }
  22.  int ChuangKou()
  23.  { // 返回空闲窗口的序号(0~Qu-1),若有多个窗口空闲,返回序号最小的。若无空闲窗口,返回Qu
  24.    int i;
  25.    for(i=0;i<Qu;i++)
  26.      if(chk[i])
  27.        return i;
  28.    return i;
  29.  }
  30.  void CustomerArrived()
  31.  { // 处理客户到达事件en(en.NType=Qu),与algo3-12.cpp不同
  32.    QElemType f;
  33.    int durtime,intertime,i;
  34.    ++CustomerNum; // 客户数加1
  35.    Random(durtime,intertime); // 生成当前客户办理业务的时间和下一个客户到达的时间间隔2个随机数
  36.    et.OccurTime=en.OccurTime+intertime; // 下一客户et到达时刻=当前客户en的到达时间+时间间隔
  37.    et.NType=Qu; // 下一客户到达事件
  38.    if(et.OccurTime<CloseTime) // 下一客户到达时银行尚未关门
  39.      OrderInsert(ev,et,cmp); // 按升序将下一客户到达事件et插入事件表ev中,在bo2-6.cpp中
  40.    f.ArrivalTime=en.OccurTime; // 将当前客户到达事件en赋给队列元素f
  41.    f.Duration=durtime;
  42.    EnQueue(q,f); // 将当前客户f入队到排队机
  43.    i=ChuangKou(); // 求空闲窗口的序号
  44.    if(i<Qu) // 有空闲窗口
  45.    {
  46.      DeQueue(q,customer[i]); // 删去排队机的排头客户(也就是刚入队的f由排队机到i号窗口)
  47.  //  if(j++<20) // 输出前20个客户到达信息及处理业务窗口信息到文件c.txt中
  48.  //    fprintf(fq,"客户到达时刻=%3d,办理业务的时间=%2d,所在窗口=%d/n",customer[i].ArrivalTime,customer[i].Duration,i);
  49.      et.OccurTime=en.OccurTime+customer[i].Duration; // 设定一个i号窗口的离开事件et
  50.      et.NType=i; // 第i号窗口的离开事件
  51.      OrderInsert(ev,et,cmp); // 将此离开事件et按升序插入事件表ev中
  52.      chk[i]=0; // i号窗口状态变忙
  53.    }
  54.  }
  55.  void CustomerDeparture()
  56.  { // 处理客户离开事件en(en.NType<Qu),与algo3-12.cpp不同
  57.    int i;
  58.    i=en.NType; // 确定离开事件en发生的窗口序号i
  59.    chk[i]=1; // i号窗口状态变闲
  60.    TotalTime+=en.OccurTime-customer[i].ArrivalTime; // 客户逗留时间=离开事件en的发生时刻-该客户的到达时间
  61.    if(!QueueEmpty(q))
  62.    { // 第i窗口的客户离开后,排队机仍不空
  63.      DeQueue(q,customer[i]); // 删去排队机的排头客户并将其赋给customer[i](排队机的排头客户去i窗口办理业务)
  64.  //  if(j++<20) // 输出前20个客户到达信息及处理业务窗口信息到文件c.txt中
  65.  //    fprintf(fq,"客户到达时刻=%3d,办理业务的时间=%2d,所在窗口=%d/n",customer[i].ArrivalTime,customer[i].Duration,i);
  66.      chk[i]=0; // i号窗口状态变忙
  67.      et.OccurTime=en.OccurTime+customer[i].Duration; // 设定customer[i]的离开事件et,客户的离开时间=原客户的离开时间+当前客户办理业务的时间
  68.      et.NType=i; // 第i号窗口的离开事件
  69.      OrderInsert(ev,et,cmp); // 将此离开事件et按升序插入事件表ev中
  70.    }
  71.  }
  72.  void main()
  73.  {
  74.  //fq=fopen("c.txt","w"); // 打开c.txt文件,用于写入客户到达信息
  75.  //fp=fopen("d.txt","w"); // 打开d.txt文件,用于写入有序事件表的历史记录
  76.    printf("请输入银行营业时间长度(单位:分): ");
  77.    scanf("%d",&CloseTime);
  78.  //srand(time(0)); // 设置随机数种子,以使每次运行程序产生的随机数不同(time(0)是长整型数,与调用时间有关)
  79.    Bank_Simulation();
  80.  //fclose(fq); // 关闭c.txt
  81.  //fclose(fp); // 关闭d.txt
  82.  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值