算法与数据结构-队列

一.队列的概念

  • 队列(Queue):也是运算受限的线性表。是一种先进先出FIFO(Last In First Out)的线性表。只允许在表的一端进行插入,而在另一端进行删除。
  • 队首(front):允许进行删除的一端称为队首。
  • 队尾(rear):允许进行插入的一端称为队尾。

二.队列的抽象数据类型

ADT Queue{
数据对象: D = { a i ∣ a i ∈ E l e m S e t , i = 1 , . . . , n , n ≥ 0 } D=\{a_i|a_i∈ElemSet,i=1,...,n,n≥0\} D={aiaiElemSet,i=1,...,n,n0}
数据关系: R = { < a i − 1 , a i > ∣ a i − 1 , a i ∈ D , i = 2 , 3 , . . . n } R=\{<a_{i-1},a_i>|a_{i-1},a_i∈D,i=2,3,...n\} R={<ai1,ai>ai1,aiD,i=2,3,...n}
约定 a 1 a_1 a1端为队首, a n a_n an端为队尾。
基本操作:
Create():创建一个空队列;
EmptyQue():若队列为空,则返回true,否则返回false;
……
InsertQue(x):向队尾插入元素x;
DeleteQue(x):删除队首元素x;
}ADT Queue

三.队列的顺序表示和实现

队列的顺序存储表示

利用一组连续的存储单元(一维数组)依次存放从队首到队尾的各个元素,称为顺序队列。类型定义如下:

#define MAX_QUEUE_SIZE 100 
typedef struct queue
{ ElemType Queue_array[MAX_QUEUE_SIZE ]; 
  int front;
  int rear;     
}SqQueue;

设立一个队首指针front,一个队尾指针rear,分别指向队首和队尾元素。
初始化:front=rear=0
入队:将新元素插入rear所指的位置,然后rear加1
出队:删去front所指的元素,然后加1并返回被删元素
队列为空:front=rear
队满:rear=MAX_QUEUE_SIZE -1或front=rear

循环队列

为充分利用向量空间,克服“假溢出”现象的方法是:将为队列分配的向量空间看成为一个首尾相接的圆环,并称这种队列为循环队列(Circular Queue)。
在循环队列中进行出队、入队操作时,队首、队尾指针仍要加1,朝前移动。只不过当队首、队尾指针指向向量上界(MAX_QUEUE_SIZE )时,其加1操作的结果是指向向量的下界0。
这种循环意义下的加1操作可以描述为:
$i=(i+1)%MAX_QUEUE_SIZE ; 显 然 , 为 循 环 队 列 所 分 配 的 空 间 可 以 被 充 分 利 用 , 除 非 向 量 空 间 真 的 被 队 列 元 素 全 部 占 用 , 否 则 不 会 上 溢 。 因 此 , 真 正 实 用 的 顺 序 队 列 是 循 环 队 列 。 1 ) r e a r 所 指 的 单 元 始 终 为 空 2 ) 循 环 队 列 为 空 : f r o n t = r e a r 3 ) 循 环 队 列 满 : ; 显然,为循环队列所分配的空间可以被充分利用,除非向量空间真的被队列元素全部占用,否则不会上溢。 因此,真正实用的顺序队列是循环队列。 1)rear所指的单元始终为空 2)循环队列为空:front=rear 3)循环队列满: ;1rear2front=rear3(rear+1)%MAX_QUEUE_SIZE=front $

  • 队列初始化
SqQueue Init_CirQueue(void)
{  SqQueue Q;
   Q.front=Q.rear=0;
   return(Q);
}
  • 入队操作
Status Insert_CirQueue(SqQueue Q,ElemType e)
/*将数据元素e插入到循环队列Q的队尾*/
{  if((Q.rear+1)%MAX_QUEUE_SIZE ==Q.front)
   return ERROR;/*队满,返回错误标志*/
   Q.Queue_array[Q.rear]=e;/*元素e入队*/
   Q.rear=(Q.rear+1)%MAX_QUEUE_SIZE ;
   /*队尾指针向前移动*/
   return OK;/*入队成功*/
}
  • 出队操作
Status Delete_CirQueue(SqQueue Q,ElemType *x)
/*将循环队列Q的队首元素出队*/
{  if(Q.front+1==Q.rear)
   return ERROR;/*队空,返回错误标志*/
   *x=Q.Queue_array[Q.front];/*取队首元素*/
   Q.front=(Q.front+1)%MAX_QUEUE_SIZE ;
   /*队首指针向前移动*/
   return OK;
}

队列的链式表示和实现

队列的链式存储表示

队列的链式存储结构简称为链队列,它是限制仅在表头进行删除操作和表尾进行插入操作的单链表。
需要两类不同的节点:数据元素节点,队列的队首指针和队尾指针的节点。

/*数据元素节点类型的定义:*/
typedef struct QNode
{ ElemType data; 
  struct QNode *next;    
}QNode;

/*指针结点类型的定义:*/
typedef struct link_queue
{ QNode *front,*rear;    
}Link_Queue;
  • 链队列的初始化
LinkQueue *Init_LinkQueue(void)
{  LinkQueue *Q;
   QNode *p;
   p=(QNode *)malloc(sizeof(QNode));/*开辟头结点*/
   p->next=NULL;
   Q=(LinkQueue *)malloc(sizeof(LinkQueue));/*开辟链队的指针结点*/
   Q.front=Q.rear=p;
   return(Q);
}
  • 入队操作
Status Insert_LinkQueue(LinkQueue *Q,ElemType e)
/*将数据元素e插入到链队列Q的队尾*/
{  p=(QNode *)malloc(sizeof(QNode));
   if(!p)
   return ERROR;/*申请新结点失败,返回错误标志*/
   p->data=e;
   p->next=NULL;/*形成新结点*/
   Q.rear->=p;
   Q.rear=p;/*新结点插入到队尾*/
   return OK;
}
  • 出队操作
Status Delete_LinkQueue(LinkQueue *Q,ElemType *x)
/*将循环队列Q的队首元素出队*/
{  QNode *p;
   if(Q.front==Q.rear)
   return ERROR;/*队空,返回错误标志*/
   p=Q.front->next;/*取队首结点*/
   *x=p->data;
   Q.front->next=p->next;/*修改队首指针*/
   if(p==Q.rear)
   Q.rear=Q.front
   /*当队列只有一个结点时应防止丢失队尾指针*/
   free(p);
   return OK;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值