zoukankan      html  css  js  c++  java
  • 浅谈数据结构之顺序队列(五)

      队列:是指只允许在一端进行插入操作,而在另一端进行删除操作的线性表。队列是一种先进先出的线性表,这与栈的后进先出正好相反;其中允许插入的一端我们称为队尾,允许删除的一端我们称为队头(或队首)。假设队列Q=(a1,a2,......an),那么a1就是队头元素,an就是队尾元素;我们删除数据时,总是从队头元素a1开始,而插入数据时,则是从队尾元素an后面开始插入,这也比较符合我们生活中的习惯,排在第一的当然优先出列,后来的当然排在队伍的后面。

      线性表有顺序存储和链式存储,栈是线性表,所以也有这两种存储方式。同样的,队列作为一种特殊的线性表,也有这两种存储方式。下面,我们先来看看队列的顺序存储结构。

      我们假设一个队列有n个元素,则顺序存储的队列需要建立一个大于n的数组,并把队列的所有元素存储在数组的前n个单元中,数组下标为0的一端即为队首。所谓的入队列操作,其实就是在队尾追加一个元素,不需要移动任何元素,因此它的时间复杂度为0(1)。与栈不同的是,队列元素的出队列在队头,这也就意味着,队列中所有元素都得向前移动,以保证队列队头元素不为空,即数组下标为0的位置不为空,此时的时间复杂度为0(n)。在现实中也是如此,比如说一群人在排队买票,前面的人买好了票就离开,后面的人则向前一步,补上前面的空位。

      通常我们为了避免当只有一个元素时,队头与队尾重合使操作变得麻烦,所以引入了两个指针,front指针指向队头元素,rear指针指向队尾元素的下一个位置,这样当front=rear时,此队列不是只剩下一个元素,而是一个空队列。若设队列的长度为QueueSize,则通用的计算队列的长度公式为:(rear-front+QueueSize)%QueueSize。接下来我们重点看一下队列的插入、删除等操作是怎样实现的,具体操作源程序代码如下所示:

      1 #include <stdio.h>
      2 #include <stdlib.h> 
      3 
      4 #define OK 1
      5 #define ERROR 0
      6 #define TRUE 1
      7 #define FALSE 0
      8 
      9 #define MAXSIZE 10                /* 存储空间初始分配量 */
     10 
     11 typedef int Status; 
     12 typedef int QElemType;             /* QElemType类型根据实际情况而定,这里假设为int */
     13 
     14 /* 循环队列的顺序存储结构 */
     15 typedef struct
     16 {
     17     QElemType data[MAXSIZE];
     18     int front;                   /* 头指针 */
     19     int rear;                    /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
     20 }SqQueue;
     21 
     22 Status visit(QElemType c)
     23 {
     24     printf("%d ",c);
     25     return OK;
     26 }
     27 
     28 /* 初始化一个空队列Q */
     29 Status InitQueue(SqQueue *Q)
     30 {
     31     Q->front=0;
     32     Q->rear=0;
     33     return  OK;
     34 }
     35 
     36 /* 将Q清为空队列 */
     37 Status ClearQueue(SqQueue *Q)
     38 {
     39     Q->front=Q->rear=0;
     40     return OK;
     41 }
     42 
     43 /* 返回Q的元素个数,也就是队列的当前长度 */
     44 int QueueLength(SqQueue Q)
     45 {
     46     return (Q.rear-Q.front+MAXSIZE)%MAXSIZE;
     47 }
     48 
     49 /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */
     50 Status GetHead(SqQueue Q,QElemType *e)
     51 {
     52     if(Q.front==Q.rear)     /* 队列空 */
     53         return ERROR;
     54     *e=Q.data[Q.front];
     55     return OK;
     56 }
     57 
     58 /* 若队列未满,则插入元素e为Q新的队尾元素 */
     59 Status EnQueue(SqQueue *Q,QElemType e)
     60 {
     61     if ((Q->rear+1)%MAXSIZE == Q->front)    /* 队列满的判断 */
     62         return ERROR;
     63     Q->data[Q->rear]=e;                     /* 将元素e赋值给队尾 */
     64     Q->rear=(Q->rear+1)%MAXSIZE;            /* rear指针向后移一位置, */
     65                                             /* 若到最后则转到数组头部 */
     66     return  OK;
     67 }
     68 
     69 /* 若队列不空,则删除Q中队头元素,用e返回其值 */
     70 Status DeQueue(SqQueue *Q,QElemType *e)
     71 {
     72     if (Q->front == Q->rear)                /* 队列空的判断 */
     73         return ERROR;
     74     *e=Q->data[Q->front];                   /* 将队头元素赋值给e */
     75     Q->front=(Q->front+1)%MAXSIZE;          /* front指针向后移一位置, */
     76                                             /* 若到最后则转到数组头部 */
     77     return  OK;
     78 }
     79 
     80 /* 从队头到队尾依次对队列Q中每个元素输出 */
     81 Status QueueTraverse(SqQueue Q)
     82 { 
     83     int i;
     84     i=Q.front;
     85     while((i+Q.front)!=Q.rear)
     86     {
     87         visit(Q.data[i]);
     88         i=(i+1)%MAXSIZE;
     89     }
     90     printf("
    ");
     91     return OK;
     92 }
     93 
     94 int main()
     95 {    
     96     SqQueue Q;
     97     QElemType e;
     98     Status i;
     99     int j,k=0;
    100 
    101     i=InitQueue(&Q);
    102     printf("1.初始化队列Q后,队列Q的长度为:Q.length=%d
    ",QueueLength(Q));
    103     
    104     printf("2.请输入整型队列元素(不超过%d个),-1为提前结束符: 
    ",MAXSIZE-1);
    105     do
    106     {
    107         e=k+10;
    108         if(e==-1)
    109             break;
    110         k++;
    111         EnQueue(&Q,e);
    112     }while(k<MAXSIZE-1);
    113     
    114     printf("3.连续%d次由队头删除元素,队尾插入元素:
    ",MAXSIZE);
    115     for(j=1;j<=MAXSIZE;j++)
    116     {
    117         DeQueue(&Q,&e);
    118         printf("删除的元素是%d,插入的元素:%d 
    ",e,j+100);
    119         e=j+100;
    120         EnQueue(&Q,e);
    121     }
    122 
    123     printf("4.现在队列中的元素为: 
    ");
    124     QueueTraverse(Q);
    125     
    126     printf("5.现在队列Q的长度为:Q.length=%d
    ",QueueLength(Q));
    127  
    128     DeQueue(&Q,&e);
    129     printf("6.在队列Q的队头处删除元素后:Q.data=");
    130     QueueTraverse(Q); 
    131     
    132     GetHead(Q,&e);
    133     printf("7.现在队列Q的队头元素是:%d
    ",e); 
    134      
    135     i=ClearQueue(&Q);
    136     printf("8.将队列Q清空后,队列Q的长度为:Q.length=%d
    ",QueueLength(Q));
    137      
    138     return 0;
    139 }
  • 相关阅读:
    ASE19团队项目 beta阶段 model组 scrum report list
    ASE19团队项目 beta阶段 model组 scrum7 记录
    ASE19团队项目 beta阶段 model组 scrum6 记录
    ASE19团队项目 beta阶段 model组 scrum5 记录
    ASE19团队项目 beta阶段 model组 scrum4 记录
    ASE19团队项目 beta阶段 model组 scrum3 记录
    ASE19团队项目 beta阶段 model组 scrum2 记录
    ASE19团队项目 beta阶段 model组 scrum1 记录
    【ASE模型组】Hint::neural 模型与case study
    【ASE高级软件工程】第二次结对作业
  • 原文地址:https://www.cnblogs.com/mix88/p/6171799.html
Copyright © 2011-2022 走看看