数据结构(C语言版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.3 典型例题

【例3.5】 循环队列应用——键盘输入循环缓冲区问题。

在操作系统中,循环队列经常用于实时应用程序。例如,当程序正在执行其他任务时,用户可以从键盘上不断输入内容,很多字处理软件就是这样工作的。系统在利用这种分时处理方法时,用户输入的内容不能在屏幕上立刻显示出来,直到当前正在工作的那个进程结束为止。但在这个进程执行时,系统在不断地检查键盘状态,如果检测到用户输入了一个新的字符,就立刻把它存到系统缓冲区中,然后继续运行原来的进程。当当前工作的进程结束后,系统就从缓冲区中取出输入的字符,并按要求进行处理。这里的键盘输入缓冲区采用了循环队列,队列的特性保证了先输入、先保存、先处理的要求,循环结构又有效地限制了缓冲区的大小,并避免了假溢出问题。下面用一段程序来模拟这种应用情况。

[问题描述]:有两个进程同时存在于一个程序中。其中第一个进程在屏幕上连续显示字符“A”,与此同时,程序不断检测键盘是否有输入,如果有,就读入用户输入的字符并保存到输入缓冲区中。在用户输入时,输入的字符并不立即显示在屏幕上。当用户输入一个逗号(,)时,表示第一个进程结束,第二个进程从缓冲区中读取那些已输入的字符并显示在屏幕上。第二个进程结束后,程序又进入第一个进程,重新显示字符“A”,同时用户又可以继续输入字符,直到用户输入一个分号(;),才结束第一个进程,同时结束整个程序。

[算法描述]:

#include "stdio.h"
#include "conio.h"
#include "dos.h"
main()
{/*模拟键盘输入循环缓冲区*/
char ch1,ch2;
SeQueue Q;
int f;
Init_Queue (&Q);   /* 队列初始化 */
for( ; ;)
{
  for( ; ;)  /*第一个进程*/
  {
    printf("A");
    if(kbhit())
      {
        ch1=getch(); /*读取输入的字符,但屏幕上不显示*/
        if (ch1==';'||ch1=='.') break; /*第一进程正常中断*/
        f=In_Queue(&Q,ch1);
        if(f==FALSE)
        {
           printf("循环队列已满\n");
           break;   /* 循环队列满时,强制中断第一个进程*/
        }
      }
    }
   while (!Empty_Queue(Q))  /*第二个进程*/
  {
     Out_Queue (&Q,&ch2);
     putchar(ch2);   /*显示输入缓冲区的内容*/
  }
  if(ch1==';')
     break;   /*整个程序结束*/
  }
}

【例3.6】 链列应用——模拟患者医院看病过程。

患者在医院看病过程:先排队等候,再看病治疗。在排队的过程中主要重复做两件事情,一是患者到达诊室时,将病历交给护士,排到等候队列中候诊;二是护士从等候队列中取出下一个患者的病历,该患者进入诊室看病。

[算法思想]:在排队时按照“先到先服务”的原则,设计一个算法模拟患者等候就诊的过程。其中,“患者到达”用命令a表示,“护士让下一位患者就诊”用命令n表示,“不再接受患者排队”用命令q表示。

本算法采用链队存放患者的病历号。

(1)当有“患者到达”命令时,则入队;

(2)当有“护士让下一位患者就诊”命令时,则出队;

(3)当有“不再接受患者排队”命令时,则队列中所有元素出队,程序终止。

[算法描述]:

void SeeDoctor()
{
Init_Queue(Q);
flag=1;
while (flag) {
     printf("\n请输入命令:");
     ch=getchar();
     switch(ch) {
                  case ‘a’: printf("\n 病历号:");
                            scanf("%d",&n);
                            In_Queue(&Q,n);
                            break;
                  case 'n': if (!Empty_Queue(Q))
                                   {Out_Queue(&Q,&n);
                                    printf("\n 病历号为%d的患者就诊", n);
                                   }
                                else
                                   printf("\n 无患者等候就诊");
                                break;
                      case ‘q’: printf("\n 停止挂号,下列患者依次就诊:");
                                while ()
                                   { Out_Queue (&Q,&n);
                                     printf("\n 病历号为%d的患者就诊", n);
                                   }
                                   flag=0;
                                   break;
                        default: printf("\n 无效命令!");
                       }
             }
}