数据结构与实训
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.6 实训例题

3.6.1 实训例题1:顺序循环队列的操作

【问题描述】

对顺序循环队列,将自然数按序入队、出队。具体的操作是:队列未满时,入队、入队、出队,输出出队元素的值;队列满时,执行连续的出队操作,输出出队元素的值(应与队列未满时所输出的有不同标识),直至队列为空。编写算法实现以上操作。

【基本要求】

队列采用顺序存储结构,涉及的操作有队列的初始化,判断队列是否为空,入队和出队。

• 功能:

(1)初始化队列;

(2)判断队列是否为空;

(3)入队;

(4)出队。

• 输入:自动生成入队值(自然数)。

• 输出:出队值与入队值相同。

【测试数据】

若MaxSize定义为20,则预期的输出结果是:

1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19#20#21#22#23#24#25#26#27#28#29#30#31#32#33#34#35#36#37#

队列未满时,出队的值后跟一个星号(*),具体是从1到18(队列中的值从19到37共19个元素);队列满后,执行连续出队,出队的值后跟一个井号(#),从19到37。

【数据结构】

顺序循环队列的定义如下。

#define MaxSize 20
typedef struct
{ int elem[MaxSize];
  int front,rear;
} CirQueue;

【算法思想】初始化队列,当队列未满时,自然数按序入队、入队、出队,并输出出队元素的值,后跟一个星号;当队列满时,出队,并输出出队元素的值,后跟一个井号,直到队空。

【模块划分】

① 初始化队列InitQueue。

② 判断队列是否为空QueueEmpty。

③ 入队AddQueue。

④ 出队DeleteQueue。

⑤ 主函数main。

【源程序】

#include <stdio.h>
#define MaxSize 20
typedef struct
{ int elem[MaxSize];
  int front,rear;
} CirQueue;
CirQueue InitQueue() /*队列初始化*/
{
   CirQueue q;
   q.front=q.rear=0;
   return(q);
}/* InitQueue */
int QueueEmpty(CirQueue q) /*判断队列是否为空*/
{
     return(q.front==q.rear);
}/* QueueEmpty */
void AddQueue(CirQueue *q,int e) /*入队列*/
{
     if (q->front==(q->rear+1) % MaxSize) /*队满*/
         printf("\nFull");
     else
     {
         q->rear=(q->rear+1) % MaxSize;
         q->elem[q->rear]=e ;
     }
} /* AddQueue */
int DeleteQueue(CirQueue *q) /*出队列*/
{
     int e;
     if (QueueEmpty(*q))
          return(0);/*返回空值*/
     else
     {
         e=q->elem[(q->front+1) % MaxSize];
         q->front=(q->front+1) % MaxSize;
         return (e);
     }
}/* DeleteQueue */
main()
{
     CirQueue *q;
     int e,i=1;
     q=(CirQueue *)malloc(sizeof(CirQueue));
     *q=InitQueue();
     printf("\n");
     while (q->front !=(q->rear+1) % MaxSize) /*队列未满时*/
     {
         AddQueue(q,i);
         i++;
         if (q->front !=(q->rear+1) % MaxSize)
         {
               AddQueue(q,i);
               i++;
               e=DeleteQueue(q);
               printf("%d*",e);
         }
     }
     while (!QueueEmpty(*q)) /*队列不空时*/
     {
         e=DeleteQueue(q);
         printf("%d#",e);
     }
}/*main*/

【测试情况】

运行程序得到的实际输出如下。

1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19#20#21#22#23#24#25#26#27#28#29#30#31#32#33#34#35#36#37#

【心得】

学生可以根据程序在计算机上调试运行,并结合自己在上机过程中遇到的问题和解决方法的体会,写出调试分析过程、程序使用方法和测试结果,提交实训报告。

3.6.2 实训例题2:括号配对

【问题描述】

输入任一表达式,“#”为表达式的结束符,试写一判断表达式中圆括号(“(”与“)”)是否配对的算法。

【基本要求】

• 功能:将表达式串存入字符数组,借助堆栈,判断字符数组中圆括号是否配对。

• 输入:表达式字符串。

• 输出:判断结果(Matched或Unmatched)。

【测试数据】

输入(a+((a+b)*c)-d/c)*e#,预期的输出是Matched。

输入(a+((a+b)*c)-d/c))*e#,预期的输出是Unmatched。

输入((a+((a+b)*c)-d/c)*e#,预期的输出是Unmatched。

【数据结构】

所有链栈LinkStack类型定义如下。

typedef struct snode
{ char data;
  struct snode *next;
}StackNode;
typedef StackNode *LinkStack;

【算法思想】

输入表达式字符串,将其存入字符数组中,借助堆栈判断字符数组中的括号是否匹配。

• 逐一处理字符数组中的字符;

• 对除“(”、“)”之外的其他字符不作处理;

• 遇左括号,左括号进栈;

• 遇右括号,则出栈,并判断出栈字符是否为左括号;

• 不是,说明括号不配对;

• 是,继续处理剩余的字符,直到表达式结束(遇“#”字符),此时若栈为空则括号配对,否则括号不配对。

【模块划分】

① 接收输入字符串EnterStr。

② 判断字符串中括号是否配对Judge。

③ 主函数main,循环调用函数EnterStr和函数Judge,当用户要求继续判断时则继续循环执行,否则结束。

【源程序】

#include "string.h"
#include "stdio.h"
typedef struct snode
{ char data;
  struct snode *next;
}StackNode;
typedef StackNode *LinkStack;
LinkStack StackInit() /*初始化堆栈*/
{
    LinkStack s;
    s=(LinkStack)malloc(sizeof(StackNode));
    s->next=0;
    return (s);
}/* StackInit */
int StackEmpty(LinkStack s) /*判断栈s是否为空*/
{
     if (s->next)
          return (0);
     else
          return(1);
}/* StackEmpty */
void Push(LinkStack s,char e) /*进栈*/
{
     LinkStack p;
     p=( StackNode *)malloc(sizeof(StackNode));/*生成新结点,并由p指向它*/
     p->data=e;
     p->next=s->next;
     s->next=p;
} /* Push*/
char Pop(LinkStack s) /*出栈*/
{
     char e;
     LinkStack p;
     if (StackEmpty(s))  /*栈空*/
         return('\0');  /* 返回空值*/
     else
     {
        p=s->next;
        s->next=p->next;
        e=p->data;
        free(p);
        return(e);
     }
} /* Pop*/
void EnterStr(char str[])
{
     printf("Input the expression string ended with '#' (length≤80):\n");
     scanf("%s",str);
}/*EnterStr*/
int Judge(char st[])
{
     int i;
     LinkStack s;
     s=StackInit();
     i=0;      /*字符数组st的工作指针*/
     while(st[i]!='#')  /*逐字符处理字符表达式的数组*/
        switch(st[i])
        {
            case '(' : {Push(s,'(');i++;break ;}
            case ')' : if (Pop(s)=='(')
                              { i++;break;}
                       else
                               return (0);
            default : i++; /*其他字符不作处理*/
        }
   if (StackEmpty(s))
        return (1);
   else
        return (0);
} /*Judge*/
main()
{
     char ch,str[80];
     int flag=1;
     while (flag)
     {
        EnterStr(str);
        if (Judge(str))
             printf("Matched\n ");
        else
             printf("Unmatched\n ");
        printf("\nDo you want to continue?(y/n):\n");
        scanf("%c",&ch);scanf("%c",&ch);
if (ch==′n′||ch==′N′) flag=0;
}
}/*main*/

【测试情况】

Input the expression string ended with '#' (length≤80):
(a+((a+b)*c)-d/c)*e#
Matched


Do you want to continue?(y/n): y Input the expression string ended with '#' (length≤80): (a+((a+b)*c)-d/c))*e# Unmatched

Do you want to continue?(y/n): y Input the expression string ended with '#' (length≤80): ((a+((a+b)*c)-d/c)*e# Unmatched Do you want to continue?(y/n): n

【心得】

学生可以根据程序在计算机上调试运行,并结合自己在上机过程中遇到的问题和解决方法的体会,写出调试分析过程、程序使用方法和测试结果,提交实训报告。