队列的基本操作的实现

队列的基本操作的实现

  1. 实验目的
    熟练掌握队列的抽象数据类型,能在相应的应用问题中正确选用它,熟练掌握队列的实现方法(顺序和链式),两种存储结构和基本操作的实现算法,注意空和满的判断条件及它们的描述方法,掌握循环队列与其它顺序结构实现上的不同及解决办法,熟悉各种队列的基本操作在循环队列上的实现

  2. 实验内容
    实现以下菜单功能,根据用户的选择调用以上各函数,检验基本操作的正确性,以备后用。除了初始化和销毁操作外,其它7个队列基本操作以及“退出”分别对应一个菜单项。初始化队列后出现该菜单,根据用户选择执行对应的队列操作,并显示结果。可循环出现菜单,直到用户选择“退出”为止,此时销毁队列,结束。

  3. 数据结构定义
    我设置了一个队列,队列中的一个每个节点为:Qnode,里面有一个只想Qnode 的指针,还存有有个rear,以及front作为指针。队列是一种先进先出的数据结构,可以使用静态存储的线性结构,也可以采用单链表来进行存储。

  4. 算法思想及算法设计
    先设计一个菜单界面,这个界面里可以调用各个其他部分的函数,提供各个函数的接口,便于之后的调用。对于每个函数的调用,具体算法如下:

Status InitQueue(Queue &q)
{
   if (!q.base)
       free(q.base);
   q.base = new Elemtype[maxsize];
   if (!q.base)
       exit(OVERFLOW);
   q.front = q.rear = 0;
   return OK;
}
Status DestrotQueue(Queue &q)
{
   q.rear = q.front = 0;
   delete q.base;
   q.base = NULL;
   return OK;
}
Status ClearQueue(Queue &q)
{
   q.rear = q.front = 0;
   return OK;
}
Status QueueEmpty(Queue q)
{
   if (q.front == q.rear)
       return OK;
   else
       return FALSE;
}
Status QueueLength(Queue q)
{
   return (q.rear - q.front + maxsize) % maxsize; //学会如何找到元素个数
}
Status GetHead(Queue q, Elemtype &e)
{
   if (QueueEmpty(q))
       return FALSE;
   e = q.base[q.front];
   return OK;
}
Status EnQueue(Queue &q, Elemtype &e)
{
   if (q.front == (q.rear + 1) % maxsize)
       return OVERFLOW;
   q.base[q.rear] = e; //考虑到闭环的情况
   q.rear = (q.rear + 1) % maxsize;
   return OK;
}
Status Dequeue(Queue &q, Elemtype &e)
{
   if (QueueEmpty(q))
       return FALSE;
   e = q.base[q.front];
   q.front = (q.front + 1) % maxsize;
   return OK;
}
Status visit(Elemtype e)
{
   printf(" %d", e);
   return OK;
}

Status QueueTraverse(Queue Q, Status (*visit)(Elemtype e))
{

   for (int i = Q.front; i != Q.rear; i = (i + 1) % maxsize)
   {
       visit(Q.base[i]);
   }
   printf("\n");

   return OK;
} 
  1. 实验代码
#include <iostream>
#include "queue.hpp"
#include "constants.h"
void pt(Queue &Q);
using namespace std;
Status InitQueue(Queue &q)
{
   if (!q.base)
       free(q.base);
   q.base = new Elemtype[maxsize];
   if (!q.base)
       exit(OVERFLOW);
   q.front = q.rear = 0;
   return OK;
}
Status DestrotQueue(Queue &q)
{
   q.rear = q.front = 0;
   delete q.base;
   q.base = NULL;
   return OK;
}
Status ClearQueue(Queue &q)
{
   q.rear = q.front = 0;
   return OK;
}
Status QueueEmpty(Queue q)
{
   if (q.front == q.rear)
       return OK;
   else
       return FALSE;
}
Status QueueLength(Queue q)
{
   return (q.rear - q.front + maxsize) % maxsize; //学会如何找到元素个数
}
Status GetHead(Queue q, Elemtype &e)
{
   if (QueueEmpty(q))
       return FALSE;
   e = q.base[q.front];
   return OK;
}
Status EnQueue(Queue &q, Elemtype &e)
{
   if (q.front == (q.rear + 1) % maxsize)
       return OVERFLOW;
   q.base[q.rear] = e; //考虑到闭环的情况
   q.rear = (q.rear + 1) % maxsize;
   return OK;
}
Status Dequeue(Queue &q, Elemtype &e)
{
   if (QueueEmpty(q))
       return FALSE;
   e = q.base[q.front];
   q.front = (q.front + 1) % maxsize;
   return OK;
}
Status visit(Elemtype e)
{
   printf(" %d", e);
   return OK;


Status QueueTraverse(Queue Q, Status (*visit)(Elemtype e))
{

   for (int i = Q.front; i != Q.rear; i = (i + 1) % maxsize)
   {
       visit(Q.base[i]);
   }
   printf("\n");

   return OK;
}

void hanshu2(Queue &q)
{
   printf("请输入要入队的元素\n");
   int x;
   scanf("%d", &x);
   EnQueue(q, x);
}
void hanshu3(Queue &Q)
{
   int e;
   Dequeue(Q, e);
   printf("出队的元素为:%d\n", e);
}
Status init(Queue &Q)
{
   int num = 0;

   do
   { //使用dowhile循环
       printf("菜单\n");
       printf("1----初始化队列\n");
       printf("2----入队\n");
       printf("3----出队\n");
       printf("4----求出队头元素\n");
       printf("5----求出队的长度\n");
       printf("6----销毁队列\n");
       printf("7----清空队列\n");
       printf("8----判断队时是否为空\n");
       printf("9----对队列进行遍历操作\n");
       printf("0----退出\n");
       scanf("%d", &num);
       switch (num)
       {
       case 1:
           InitQueue(Q);
           break;
       case 2:
           hanshu2(Q);
           break;
       case 3:
           hanshu3(Q);
           break;
       case 4:
       {
           int e;
           GetHead(Q, e);
           printf("队头元素为:%d\n", e);
       }
       break;
       case 5:
       {
           printf("队长度为:%d\n", QueueLength(Q));
       }
       break;
       case 6:
       {
           printf("你确定要销毁队列吗??\n1---YES\n2---NO\n");
           int x;
           scanf("%d", &x);
           if (x == 1)
               DestrotQueue(Q);
       }
       break;
       case 7:
       {
           printf("你确定要清空队列吗??\n1---YES\n2---NO\n");
           int x;
           scanf("%d", &x);
           if (x == 1)
               ClearQueue(Q);
       }
       break;
       case 8:
       {
           if (QueueEmpty(Q))
               printf("该队列为空\n");
           else

               printf("该队列非空\n");
       }
       break;
       case 9:
       {
           QueueTraverse(Q, visit);
       }
       break;
       default:
           return 0;
       }

   } while (num != 0);
   return OK;
}
void pt(Queue &Q)
{
   for (int i = Q.front; i != Q.rear; i = (i + 1) % maxsize)
       printf("%d ", Q.base[i]);
   printf("\n");
}
int main(int argc, char *argv[])
{
   Queue Q;
   InitQueue(Q);
   //int x=4;
   //EnQueue(Q, x);
   //pt(Q);
   //int y;4
   //GetHead(Q, y);
   //printf("hnbb    %d\n",QueueLength(Q));
   init(Q);
}


  1. 算法测试结果
    对菜单的每个操作进行演示:具体演示如下:

  2. 分析与总结
    (1)算法复杂度分析及优、缺点分析
    算法的时间复杂度根据各个操作有所不同,除了对队列进行的遍历操作为O(N)之外,其余均为O(1),时间复杂度很低,非常适合操作。算法的优点是每一个都有一个固定的模块,算法结构性很好,对于整体的编程来说非常友好。缺点是由于是线性结构,算法其本身有局限性,入出队列要求高,不是随便出入。
    (2)实验总结
    写算法时判断队空以及队满的情况,没有分析清楚,不能更加准确的找到如何判断这两个操作,以至于后期出现段错误,导致没法进行程序。还有注意运用循环队列使整个空间能够更加好的运用,更好的利用所有空间。

上一篇:js类似promise的手写实现


下一篇:C语言实现字符界面贪吃蛇