跳至主要內容

2.队列


队列的顺序存储结构

顺序存储

定义

分配一块连续的存储单元,队头指针front指向队头元素,队尾指针rear指向队尾元素的下一个位置[1]

  • 初始化:Q.front=Q.rear=0
  • 进队:队不满时,先送值,队尾再加1
  • 出队:队不空时,先取值,队头再加1
  • 队为空:Q.front=Q.rear=0
  • 队满:Q.rear == MaxSize可能存在“假溢出”
#define MaxSize 50
typedef struct{
	ElemType data[MaxSize];
	int front,rear;
}SqQueue;

循环队列

解决假溢出

采用循环队列解决假溢出现象,存储队列元素的表从逻辑上视为一个环。

  • 初始时:Q.front=Q.rear=0
  • 队首指针进1:Q.front=(Q.front+1)%MaxSize
  • 队尾指针进1:Q.rear=(Q.rear+1)%MaxSize
  • 队列长度:(Q.rear+MaxSize-Q.front)%MaxSize
  • 出队入队时:指针都按顺时针方向进1。

区分队空队满

  1. 牺牲一个单元来区分,队头指针在队尾指针的下一个位置视为队满。
    1. 队满:(Q.rear+1)%MaxSize==Q.front
    2. 队空:Q.front==Q.rear
    3. 元素个数:(Q.rear+MaxSize-Q.front)%MaxSize
  2. 类型中增设表示元素个数的数据成员。这样,队空的条件为Q.size==0;队满的条件为Q.size==MaxSize。这两种情况都有Q.front==Q.rear
  3. 类型中增设tag数据成员,以区分是队满还是队空。tag等于0时,若因删除导致Q.front==Q.rear,则为队空:tag等于1时,若因插入导致Q.front==Q.rear,则为队满。

队列的链式存储结构

实际是一个同时带有队头指针和队尾指针的单链表[2],头指针指向队头结点,尾指针指向队尾结点

typedef struct LinkNode{
	ElemType data;
	struct LinkNode *next;
}LinkNode;
typedef struct{
	LinkNode *front,*rear;
}*LinkQueue;
  • 队空:Q.front==NULL && Q.rear==NULL
  • 进队:将新结点插入到链表的尾部,并让Q.rear指向这个新插入的结点[3]
  • 出队:若不为空,取出队头元素将其从链表中摘除,并让Q.frot指向下一个结点[4]

双端队列

两端都可以入队出队


  1. 不同教材对front和rear的定义可能不同 ↩︎

  2. 所以也不存在假溢出现象 ↩︎

  3. 若原队列为空队,则令Q.front也指向该结点 ↩︎

  4. 若该结点为最后一个结点,则置Q.front和Q.rear都为NULL ↩︎