数据结构-循环队列顺序存储

本文介绍了如何实现循环队列的顺序存储,强调了入队操作需逐个元素进行,并指出了在处理输入时的一个常见问题:原框架中使用scanf()判断输入可能导致无法正确检测非法值。解决方案是修改输入判断方式,确保能捕获无效输入。
摘要由CSDN通过智能技术生成

目标效果:


dsp0304.cpp:

#include <stdio.h>
#include <stdlib.h>
#include "sqqueue.h"

//初始化系统
void Initialize(SqQueue &q);
//显示操作菜单
void ShowMenu();
//读取用户命令
int GetCommand();
//执行用户命令
int DoCommand(int cmd, SqQueue &q);
//结束执行
void Finalize(SqQueue &q);

void QueueView(SqQueue Q);


//主程序
int main()
{
    SqQueue q; //循环队列
    int cmd; //用户命令

    //系统初始化
    Initialize(q);
    //显示操作菜单
    ShowMenu();
    //进入主循环
    while(1) {
        //读取用户命令(0 表示退出)
        cmd = GetCommand();
        //执行命令cmd操作队列q
        DoCommand(cmd,q);
        //退出命令
        if( cmd == 0 ) break;  // 退出
    }

    //结束前执行的操作
    Finalize(q);

    system("pause"); //暂停
	return 0;
}


//函数的定义

//初始化系统
void Initialize(SqQueue &q)
{
    InitQueue(q); //初始化队列
}

//显示操作菜单
void ShowMenu()
{
    printf("1)EnQueue 2)DeQueue 3)Clear 4)Empty"
           " 5)Length 6)Head 7)View 9)Menu 0)Quit\n");
}

//读取用户命令
int GetCommand()
{
    int cmd=-1;
    printf(">");
    scanf("%d", &cmd);
    if(cmd<1)
        fflush(stdin); //处理输入错误
    return cmd;
}

//结束执行
void Finalize(SqQueue &q)
{
    DestroyQueue(q); //销毁队列
    printf("程序已经结束\n");
}

//执行用户命令cmd, 测试队列的各种操作
//    执行结束后返回命令(便于书写主循环)
int DoCommand(int cmd, SqQueue &q)
{
    int e;

    switch(cmd) {
    case 1: //EnQueue......................
        printf("输入入队列的数据:");
		scanf("%d",&e);
        if(e<1) {
            printf("输入错误\n");
            fflush(stdin);
        } else if(EnQueue(q,e)==OK)
            printf("入队列成功\n" );
        else
            printf("入队列失败\n");
        break;
    case 2: //DeQueue......................
        if( DeQueue(q,e)==OK )
            printf("%d 出队列\n", e);
        else
            printf("出队列失败\n");
        break;
    case 3: //Clear........................
        if(ClearQueue(q)==OK)
            printf("队列已清空\n");
        else
            printf("清空队列失败\n");
        break;
    case 4: //Empty........................
        if(QueueEmpty(q)==TRUE)
            printf("队列空\n" );
        else
            printf("队列不空\n");
        break;
    case 5: //Length.......................
        printf("队列长度: %d\n", QueueLength(q));
        break;
    case 6: //Head.........................
        if(GetHead(q,e)==OK)
            printf("队头元素: %d\n", e);
        else
            printf("取队头元素失败\n");
        break;
    case 7: //View.........................
        /* TODO (#9#): 实现SqQueue类型后使用QueueView()函数 */
        QueueView(q);
        break;
    case 9: //Menu.........................
        ShowMenu();
    case 0: //Quit.........................
        //后面 return cmd; 返回0可以结束主循环
        break;
    default:
       printf("命令错误\n");
    }

    return cmd; //返回最近执行的命令
}



squeue.h:
#ifndef SQQUEUE_H_INCLUDED
#define SQQUEUE_H_INCLUDED /* 防止重复包含 */

//
//包含头文件
#include <stdlib.h>
#include "ds.h" // OK, Status 等定义

//数据元素的类型(缺省使用int型)
#ifndef ElemType
#define ElemType int
#define USE_DEFAULT_ELEMTYPE /* 使用缺省类型的标志 */
#endif //ElemType

//
//循环队列的存储结构

#define MAXQSIZE 64 /* 循环队列的最大容量 */
typedef struct {
	ElemType *base;
	int front;
	int rear;
} SqQueue;


//
//循环队列的基本操作

//构造一个空队列Q
Status InitQueue(SqQueue &Q)
{
	Q.base=(ElemType *)malloc(MAXQSIZE*sizeof(ElemType));
	if(!Q.base)
		return ERROR; //TODO: 替换这行代码,以下同
	Q.front=Q.rear=0;
	return OK;
}

//销毁队列Q
//  前提:队列Q已存在
Status DestroyQueue(SqQueue &Q)
{
	if(!Q.base)
		return ERROR;
	Q.rear=Q.front;
	free(Q.base);
	return OK;
}

//将队列Q清为空队列
//  前提:队列Q已存在
Status ClearQueue(SqQueue &Q)
{
    if(!Q.base)
		return ERROR;
	Q.rear=Q.front;
	return OK;
}

//若队列Q为空,则返回TRUE,否则FALSE
//  前提:队列Q已存在
Status QueueEmpty(SqQueue Q)
{
	if(Q.rear==Q.front)
		return TRUE;
    return FALSE;
}

//返回队列Q的元素个数,即队列长度
//  前提:队列Q已存在
int QueueLength(SqQueue Q)
{
    return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}

//取队列Q头元素用e返回
//  前提:队列Q存在且非空
Status GetHead(SqQueue Q, ElemType &e)
{
	if(!Q.base&&Q.rear==Q.front)
		return ERROR;//返回操作状态(成功:OK,失败:ERROR)
	e=Q.base[Q.front];
	return OK;
}

//插入元素e作为队列Q的新的队尾元素
//  前提:队列Q存在且未满
Status EnQueue(SqQueue &Q, ElemType &e)
{
	if((Q.rear+1)%MAXQSIZE==Q.front)
		return ERROR;//返回操作状态(成功:OK,失败:ERROR)
	Q.base[Q.rear]=e;
	Q.rear=(Q.rear+1)%MAXQSIZE;
	return OK;
}

//删除队列Q的队头元素,并用e返回
//  前提:队列Q存在且非空
Status DeQueue(SqQueue &Q, ElemType &e)
{
	if(Q.front==Q.rear)
		return ERROR;//返回操作状态(成功:OK,失败:ERROR)
	e=Q.base[Q.front];
	Q.front=(Q.front+1)%MAXQSIZE;
	return OK;
}

//


//TODO: 定义好 SqQueue 类型后使用 QueueView 函数
//#include <stdio.h>
//查看队列状态(调试用)
void QueueView(SqQueue Q)
{
   int i=0;
   if(Q.front<0||Q.front>=MAXQSIZE||Q.rear<0||Q.rear>=MAXQSIZE){
       printf("队列未初始化\n");
       return ;
   }
   printf("---Queue View---\n");
   printf("front=%d , rear=%d\n", Q.front, Q.rear);
   if(Q.rear>=Q.front) {
       printf(".....   ......\n");
       for(i=Q.front; i<Q.rear; i++) {
           printf("%5d\t", i);
		   printf("%d",Q.base[i]);
           printf("\n");
       }
       if(i<MAXQSIZE) printf(".....   ......\n");
   } else {
       for(i=0; i<Q.rear; i++) {
           printf("%5d\t", i);
		   printf("%d",Q.base[i]);
           printf("\n");
       }
       printf(".....   ......\n");
       for(i=Q.front; i<MAXQSIZE; i++) {
           printf("%5d\t", i);
		   printf("%d",Q.base[i]);
           printf("\n");
       }
   }
   printf("--- view end ---\n");
}

//取消ElemType的默认定义,以免影响其它部分
#ifdef USE_DEFAULT_ELEMTYPE
#undef ElemType
#undef USE_EFAULT_ELEMTYPE
#endif

#endif //SQQUEUE_H_INCLUDED


源码下载:点击打开链接


1.前几次我一直没有加ds.h页面,里边就是定义了return ok这种形式,以及read读入方法的总写,没比较核心的内容,所以之前我都去掉这个页面,方法返回值return ok都用return true来表示。不够今天不太想那样改了,没多大用,纯自己的强迫症。代码没贴出来,不过在代码链接里可以下载。

2.这里的入队需要单个元素进行入队。

3.另外注意一个地方,原先老师发的框架里,输入一个数值并判断是  if(scanf("%d", &cmd)<1),但是这样即使输入了一个不合法的值还是不会进if语句,后来查了一个是因为scanf()有返回值,但是会返回本次输入的个数,因为入队每次都是1个元素,所以scanf()返回的都是1,所以不会进入if语句,这里需要改成我代码中的格式,即先输入然后判断。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值