队列(循环队列,链队)总结

像栈一样,队列也是一种线性表。它允许在表的一端插入数据,在另一端删除元素。插入元素的这一端称之为队尾。删除元素的这一端我们称之为队首。

队列的特性:

1.在队尾插入元素,在队首删除元素。

2.先进先出(排队一样)

 

目录

一.循环队列​

注意事项:

定义循环队列

初始化

 判空

求循环队列的长度

入队列

出队列

取队头元素

二.链队列

链队列定义

初始化

判空

入队列

出队列

取队头元素


一.循环队列

  • 注意事项:

1.入队可能会越界?

如果是在普通的队列中,那么插入元素,直接将tail + 1即可。可是在循环队中,元素插入的位置可能是原来队首的位置,如上图中的I,这样如果直接用tail + 1就会造成越界。所以我们计算数组下标的时候要进行取模。使用( tail + 1 ) % n。同理,删除元素也是类似。

2.如何判断队列是否为空,队列是否为满呢?

从上面的图可以看出当tail == head的时候,这个是否队列是即可以为空,又可以为满。那么我们不妨将队列最后一个元素的空气预留出来。这样的话当tail == head的时候,队列为空。当队列的tail + 1 == head,我们就认为队列已经满了,因为是循环队列,所以计算tail + 1 == head应该算上偏移量即 ( tail + 1 ) % n = head % n

  • 定义循环队列

#define MAXQSIZE 100  //最大队列长度
typedef struct
 {
 
    ElemType *base;    //初始化动态分配空间
    int  front;
    int  rear;
} SqQueue;
  • 初始化

int InitQueue(SqQueue &Q)
{
//构造一个空队列
    Q.base=(BiTree *)malloc(MAXQSIZE * sizeof(BiTNode));
    if (! Q.base)  return 0;
    Q.front=Q.rear=0;
        return 1;
} //InitQueue
  •  判空

int EmptyQueue(SqQueue Q)//判队空
{
    if(Q.front==Q.rear)
        return 1;
    else
        return 0;
}
  • 求循环队列的长度

int QueueLength(SqQueue &Q)
{
	return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}
  • 入队列

void EnQueue(SqQueue &Q,ElemType e)
{
//插入元素e为Q的新的队尾元素
    if ((Q.rear+1)%MAXQSIZE==Q.front)
        return;
    Q.base[Q.rear]=e;
    Q.rear=(Q.rear+1)%MAXQSIZE;
}
  • 出队列

void DeQueue(SqQueue &Q,ElemType &e)
{// 删除Q的队头元素,并用e返回其值
 
    if(Q.front==Q.rear)
        return;
    e=Q.base[Q.front];
    Q.front=(Q.front+1) % MAXQSIZE;
}
 
  • 取队头元素

void GetHead(SqQueue Q,ElemType &e)
{
	if(Q.rear==Q.front)
		return;
	e=Q.base[Q.front];
}

 

二.队列

队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列

为了操作上的方便,我们将队头指针指向链队列的头结点(链队列front没有值,而循环队列的front是有值的),而队尾指针指向终端结点。链队列示意图:

这里写图片描述

当队列为空时,front和rear都指向头结点。

这里写图片描述

  • 链队列定义

///队列
typedef struct QNode
{
    ElemType data;
	struct QNode *next;
}QNode,*QueuePtr;
 
typedef struct
{
    QueuePtr Front;///队头指针
    QueuePtr Rear;///队尾指针
}LinkQueue;
  • 初始化

void InitQueue(LinkQueue &Q)
{
    Q.Front=Q.Rear=(QueuePtr)malloc(sizeof(QNode));///生成新结点作为头结点,队头和队尾指针指向此结点
    if(!Q.Front)
        return;
    Q.Front->next=NULL;///头结点的指针域置空
}
  • 判空

int QueueEmpty(LinkQueue Q)
{
    if(Q.Front==Q.Rear)
        return 1;
    return 0;
}
 
  • 入队列

void EnQueue(LinkQueue &Q,ElemType e)
{
    QueuePtr s;
    s=(QueuePtr)malloc(sizeof(QNode));
    s->data=bt;
    s->next=NULL;
    Q.Rear->next=s;///将新结点插入到队尾
    Q.Rear=s;///修改队尾指针
}
  • 出队列

void DeQueue(LinkQueue &Q,ElemType &e)
{
	if(Q.Front==Q.Rear)
		return;
    QueuePtr s;
	s=Q.Front->next;		///p指向队头
	Q.Front->next=s->next;
    bt=s->data;//回收		///修改头指针
	if(Q.Rear==s)
		Q.Rear=Q.Front;		///最后一个元素被删,队尾指针指向头结点
	free(s);
}
  • 取队头元素

void GetHead(LinkQueue Q,ElemType &e)
{
	if(Q.Rear==Q.Front)
		return;
	e=Q.front->next->data;
}

 

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