26-顺序队列的基本操作

1. 队列

  队列(queue)是一种运算受限的线性表,仅允许在表的一端进行插入,而在表的另一端进行删除。进行插入的一端叫做队尾,进行删除的一端叫做队头。

队列的操作:
  向队列中插入新元素称为进队或入队,新元素进队后就成为新的队尾元素
  从队列中删除元素称为出队或离队,元素出队后,其后继元素就成为队首元素



从队列的基本概念和操作来看,队列是一种具有先进先出特点的数据结构。

26-顺序队列的基本操作_第1张图片

  假设队列中有n个元素,其中a1是队头元素,an为队尾元素,那么在删除元素时就可以从a1开始,在插入新元素时就可以从an后面进行插入。

2. 队列的抽象数据类型

ADT Queue
{
数据对象:
    D = {ai | ai∈ElemType, i=1,2,…,n, n≧0 } //ElemType为类型标识符
数据关系:
    R = {1> | ai, ai+1∈D, i=1,3,…,n-1 }
数据操作:
    InitQueue(&q):初始化队列。构造一个空队列q。
    DestroyQueue(&q):销毁队列。释放队列q占用的存储空间。
    QueueEmpty(q):判断队列是否为空。若队列q为空,则返回真;否则返回假。
    enQueue(&q,e):进队列。将元素e进队作为队尾元素。
    deQueue(&q,&e):出队列。从队列q中出队一个元素,并将其值赋给e。
}

3. 队列的顺序存储结构

  对于队列的顺序存储结构来说,队列中的数据元素data都是具有同一数据类型(ElemType),通过MaxSize我们可以确定队列的存储空间,可以利用顺序存储结构把这些数据元素data保存下来,当操作队列时同时还需要关注队首(front)和队尾(rear)。


定义队列的存储结构:

typedef struct
{
    ElemType data[MaxSize];  //定义数组存储空间
    int front;     //队首指针
    int rear;        //队尾指针
} SqQueue;

在队列的四要素中,rear指向队尾元素,front指向队头元素的前一个位置:

26-顺序队列的基本操作_第2张图片

  1. 当初始化一个队列的时候,队列中的队首(front)和队尾(rear)应该指向-1,表示还没有指向有效位置

  2. 当数据元素a,b,c,d按次序入队时,每次数据元素入队都是从队尾(rear)开始的,所以队尾(rear)的指向一直在增加,由于没有数据元素出队,队首(front)的指向还是-1。

  3. 当数据元素出队时,总是在队首进行的,当数据元素a要出队时,队首(front)就应该指向数据元素a的位置。

  4. 当队列中的所有数据元素都出队时,队首(front)会指向最后一个数据元素d的位置,此时队首和队尾的位置相同,队列为空。

队列四要素总结:
  队空条件:front == rear
  队满条件:rear == MaxSize-1
  元素e进队:rear++ ; data[rear] == e
  元素e出队:front++ ; e == data[front];

4. 顺序队列的基本操作

1.初始化队列InitQueue(q)

  创建一个空队列q,将front和rear指针均初始化为-1值

26-顺序队列的基本操作_第3张图片

void InitQueue(SqQueue *&q)
{
    q=(SqQueue *)malloc (sizeof(SqQueue));
    q->front=-1;
    q->rear=-1;
}

2.销毁队列DestroyQueue(q)

  释放队列q占用的存储空间

void DestroyQueue(SqQueue *&q)
{
    free(q);
}

3.队列是否为空QueueEmpty(q)

   若队列q满足q->front==q->rear条件,则说明队列为空,否则不为空

26-顺序队列的基本操作_第4张图片

bool QueueEmpty(SqQueue *q)
{
    return(q->front==q->rear);
}

4.入队列enQueue(q,e)

  在进行入队操作时,应该先判断队列是否已满。如果队列不满则将队尾(rear)+1,然后将元素入队

26-顺序队列的基本操作_第5张图片

bool enQueue(SqQueue *&q,ElemType e)
{
    if (q->rear==MaxSize-1)
        return false;
    q->rear++;
    q->data[q->rear]=e;
    return true;
}

5.出队列deQueue(q,e)

  在进行出队操作时,也应该先判断队列是否已满,如果队列不满则将队首(front)+1,将该位置的元素值赋给e

26-顺序队列的基本操作_第6张图片

bool deQueue(SqQueue *&q,ElemType &e)
{
    if (q->front==q->rear)
        return false;
    q->front++;
    e=q->data[q->front];
    return true;
}

5. 顺序队列的问题

26-顺序队列的基本操作_第7张图片

  假设这么一种情况,队列的存储空间可以存储5个数据元素,在开始时,一直往队列中加入元素a,b,c,d,e,当队列满时,rear指向下标为4的位置,此时队列无法再加入新的元素。

26-顺序队列的基本操作_第8张图片

  当队列满时,就一直将队列中的元素全部出队,当最后一个元素e出队时,队列就为空,队首(front)也会指向下标为4的位置。

26-顺序队列的基本操作_第9张图片

  此时就会造成队尾(rear)和队首(front)指向同一位置,由于队首(front)指向了队列的末尾,说明队列为空,但是由于队尾(rear)也指向了队列的末尾,就会造成一种“队列已满”的假象,但事实上并非如此,因此这将会造成队列空间的浪费。也就是说顺序队列可能会出现“队列已满”的假象,导致存储空间不足。

你可能感兴趣的:(数据结构基础)