队列的定义和算法的实现

与栈相反,队列(queue) 是一种先进先出 (first in first out,缩写为FIFO )的线性表。它只允许在表的一端进行插入,而在另一端删除元素。在队列中,允许插入的一端叫做队尾 (rear),允许删除的一端则称为 队头(front)。

1、链队列–队列的链式表示和实现

用链表表示的队列简称为链队列 ,一个链队列需要两个分别指示队头和队尾的指针(分别称为头指针和尾指针)才能唯一确定。我们给链队列添加一个头结点,并令头指针指向头结点。因此,空的链队列的判决条件为头指针和尾指针均指向头结点。如下图所示。

链队列的实现(部分)

(1)单链队列–队列的链式存储结构

typedef struct QNode{
  QElemType data;
  struct QNode *next;
}QNode, *QueuePtr;

typedef struct{
  QueuePtr front;  // 队头指针
  QueuePtr rear;   // 队尾指针
}LinkQueue;

(2)基本操作的算法描述(部分)

// 构造一个空队列(初始化)
Status InitQueue(LinkQueue &Q){
  Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
  if(!Q.front) exit(OVERFLOW);  // 存储分配失败
  Q.front->next = NULL;
  return OK;
}

// 销毁队列Q
Status DestroyQueue(LinkQueue &Q){
  while(Q.front){
    Q.rear = Q.front -> next;
    free(Q.front);
    Q.front = Q.rear;
  }
  return OK;
}

// 插入元素e为Q的新的队尾元素
Status EnQueue(LinkQueue &Q, QElemType e){
  p = (QueuePtr)malloc(sizeof(QNode));
  if(!p) exit(OVERFLOW);  // 存储分配失败
  p->data = e;
  p->next = NULL;
  Q->rear->next = p;
  Q.rear = p;
  return OK;
}

// 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;
// 否则返回ERROR
Status DeQueue(LinkQueue &Q, QElemType &e){
  if(Q.front == Q.rear) return ERROR;
  p = Q.front->next;
  e = p->data;
  Q.front->next = p->next;
  if(Q.rear == p) Q.rear = Q.front;
  free(p);
  return OK;
}

2、循环队列–队列的顺序表示和实现

将顺序队列臆造为一个环状的空间,如下图所示,称为循环队列。图(a)所示循环队列中,队列头元素是 J 3 J_3 J3 ,队列尾元素是 J 6 J_6 J6 ,之后 J 7 、 J 8 、 J 9 和 J 10 J_7、J_8、J_9和J_{10} J7J8J9J10 相继插入,则队列空间均被占满,如图(b)所示,此时 Q . f r o n t = Q . r e a r Q.front=Q.rear Q.front=Q.rear ;反之,若 J 3 、 J 4 、 J 5 和 J 6 J_3、J_4、J_5和J_{6} J3J4J5J6 相继从图(a)的队列中删除,使队列呈“空”的状态,如图(c)所示。此时也存在关系式 Q . f r o n t = Q . r e a r Q.front=Q.rear Q.front=Q.rear ,由此可见,只凭等式 Q . f r o n t = Q . r e a r Q.front=Q.rear Q.front=Q.rear 无法判别队列空间是“空”还是“满”。可有两种处理方法:(1)、 另设一个标志以区别队列是“空”;(2)、 少用一个元素空间,约定以“队列头指针在队列尾指针的下一位置(指环状的下一位置)上”作为队列呈“满”状态的标志。

从上述分析可见,在 C C C 语言中不能用动态分配的一维数组来实现循环队列。如果程序中设有循环队列,则必须为它设定一个最大队列长度;若无法预估所用队列的最大长度,则宜采用链队列。

CSDN图标
循环队列类型的模块说明如下:

(1)循环队列–队列的顺序存储结构

#define MAXQSIZE 1000  // 最大队列长度
typedef struct{
	QElemType *base;  // 初始化的动态分配存储空间
	int front;        // 头指针,若队列不空,指向队列头元素
	int rear;         // 尾指针,若队列不空,指向队列尾元素的下一个位置
}SqQueue;

(2)循环队列的基本操作的算法描述

// 构造一个空队列Q
Status InitQueue(SqQueue &Q){
	Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));
	if(!Q.base) exit(OVERFLOW);  // 存储分配失败
	Q.front = Q.rear = 0;
	return OK;
}

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

// 插入元素e为Q的新的队尾元素
Status EnQueue(SqQueue &Q, QElemType e)
{
	if((Q.rear + 1)%MAXQSIZE == Q.front) return(ERROR);  // 队列满
	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1)%MAXQSIZE;
	return(OK);
}

// 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK
// 否则返回ERROR
Status DeQueue(SqQueue &Q, QElemType &e)
{
	if(Q.front == Q.rear) return(ERROR);
	e = Q.base[Q.front];
	Q.front = (Q.front + 1)%MAXQSIZE;
	return(OK);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值