首页 > 其他分享 >队列

队列

时间:2023-02-01 23:33:04浏览次数:47  
标签:MAXQSIZE 队列 int base front rear

队列

是一种先进先出线性表,FIFO表的一段(表尾)插入,表的另一点端(表头)删除 ;同线性表一样仍为一对一关系;有顺序队或链队;只能在队首或队尾操作

Q=(a1队头,a2,...,an队尾)


线性表:

Insert(L,i,x)

1<=i<=n+1

Delete(L,i)

1<=i<=n


队列(先进先出,表尾进表头删):

Insert(Q,n+1,x)

Delete(Q,1


队列的抽象数据类型定义

ADT Queue{

​ 数据对象:D=ai|ai属于Elemset,i=1,2,...,n,n>=0}

​ 数据关系:R1=<ai-1,ai>|ai-1,ai属于D,i=2,3,...,n}

                 约定an为队尾,a1为队头

​ 基本操作:

​ InitQueue(&Q)

​ 操作结果:构造一个空队列Q

​ DestroyQueue(&Q)

​ 初始条件:队列Q已存在

​ 操作结果:队列Q被销毁

​ ClearQueue(&Q)

​ 初始条件:队列Q已存在

​ 操作结果:队列Q被清空

​ QueueLength(Q)

​ 初始条件:队列Q已存在

​ 操作结果:返回Q的元素个数,即队列的长度

​ GetHead(Q,&e)

​ 初始条件:队列Q已存在且非空

​ 操作结果:用e返回Q的队头元素

​ EnQueue(&Q,e)

​ 初始条件:队列Q已存在

​ 操作结果:插入元素e为Q的队尾元素

​ DeQueue(&Q,&e)

​ 初始条件:队列Q已存在且非空

​ 操作结果:删除Q的队头元素,并用e返回其值

​ ......

}ADT Queue


顺序队列

image


  • rear=MAXQSIZE front=0 再入队 真溢出
  • rear=MAXQSIZE front0 再入队 假溢出

解决假上溢可使用循环队列 :base[0]接在base[MAXQSIZE-1]后,若rear+1=M,令rear=0

插入元素:Q.base[Q.rear]=x;Q.rear=(Q.rear+1)%MAXQSIZE;

删除元素:x=Q.base[Q.front];Q.front=(Q.front+1)%MAXQSIZE;


队满:front==rear

队空:front==rear

解决方法:

  1. 另外设一个标志来区别队空、队满
  2. 另外设一个变量记录元素个数
  3. 少用一个元素空间(队尾指针再+1与头指针重合):队满:(rear+1)%MAXQSIZE==front

循环队列的定义

#define MAXQSIZE 100

typedef struct{
    int *base;      //动态分配存储空间
    int front;      //头指针
    int rear;       //尾指针
}SqQueue;

循环队列的初始化

void InitQueue(SqQueue *Q){
    Q->base=malloc(sizeof(int)*MAXQSIZE);   //分配数组空间
    if(!Q->base) printf("Error");
    Q->front=Q->rear=0;
}

求循环队列的长度

(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE

int LengthQueue(SqQueue Q){
    return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}

循环队列的入队

队满:(Q->rear+1)%MAXQSIZE==Q->front

Q.base[Q.rear]=x;Q.rear=(Q.rear+1)%MAXQSIZE;

void EnQueue(SqQueue *Q,int e){
    if((Q->rear+1)%MAXQSIZE==Q->front) printf("Error");     //如果队满
    Q->base[Q->rear]=e;
    Q->rear=(Q->rear+1)%MAXQSIZE;
}

循环队列的出队

队空:Q->rear==Q->front

x=Q.base[Q.front];Q.front=(Q.front+1)%MAXQSIZE;

void DeQueue(SqQueue *Q,int *e){
    if(Q->rear==Q->front) printf("Error");
    *e=Q->base[Q->front];
    Q->front=(Q->front+1)%MAXQSIZE;
}

链队

若用户无法估计所用队列的长度,则宜使用链队(有头结点

image


链队列的定义

#define MAXQSIZE 100

typedef struct Qnode{
    int data;
    struct Qnode *next;
}QNode,*QueuePtr;

typedef struct {
    QueuePtr front;
    QueuePtr rear;
}ListQueue;

链队列的初始化

void InitQueue(LinkQueue *Q){
    Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
    if(!Q->front) printf("Error");
    Q->front->next=NULL;
}

求循环队列的长度

(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE

int LengthQueue(SqQueue Q){
    return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}

链队列的销毁

从头指针开始

void DestroyQueue1(LinkQueue *Q){
    while (Q->front){
        QueuePtr p;
        p= Q->front->next;
        free(Q->front);     //从头结点开始销毁
        Q->front= (QueuePtr) p;
    }
}

void DestroyQueue2(LinkQueue *Q){
    while (Q->front){
        Q->rear=Q->front->next;
        free(Q->front);
        Q->front=Q->rear;
    }
}

链队列的入队

void EnQueue(LinkQueue *Q,int e){
    QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
    if (!p) printf("Error");
    p->data=e;
    p->next=NULL;
    Q->rear->next=p;
    Q->rear=p;
}

链队列的出队

void DeQueue(LinkQueue *Q,int *e){
    QueuePtr p;
    if(Q->rear==Q->front) printf("Error");
    p=Q->front->next;
    *e=p->data;
    Q->front->next=p->next;
    if(Q->rear==p) Q->rear=Q->front;
    free(p);
}

队列的应用

  • 舞伴问题:

    • 构造出两个空的队列QM,QW
    • 依次将队头元素出队配成舞伴
    • 某队为空,另一队等待的下一曲继续配对
  • 脱机打印输出,按申请先后次序输出

  • 多用户系统中,多个用户排成队,分时地循环使用CPU和主存

  • 按用户的优先级排成多个队,每个优先级一个队列

  • 实时控制系统中,信号按接收的先后顺序依次处理

  • 网络电文传输,按到达的时间先后顺序依次进行

标签:MAXQSIZE,队列,int,base,front,rear
From: https://www.cnblogs.com/yuanyu610/p/17084502.html

相关文章

  • 数据结构——优先队列
    一、优先队列优先队列顾名思义,就是优先权最大的排在队列的头部,而优先权的判断是根据对象的compare方法比较获取的,保证根节点的优先级一定比子节点的优先级大。所以放入到优......
  • 数据结构——队列
    简介队列是是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。 队列是一种先进先出的线性表,简称FIFO允许插入的以端称为队尾,允许删除的一端被称为队头。入......
  • LeetCode.225 用队列实现栈
    1题目请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop和empty)。实现MyStack类:voidpush(intx)将元素x压入栈顶。intpop()......
  • LeetCode.232 用栈实现队列
    1.题目请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):实现MyQueue类:voidpush(intx)将元素x推到队列的末尾intpop()......
  • 【算法训练营day35】LeetCode860. 柠檬水找零 LeetCode406. 根据身高重建队列 LeetCod
    LeetCode860.柠檬水找零题目链接:860.柠檬水找零独上高楼,望尽天涯路本来以为只想到了最笨的方法,即讨论所有情况。classSolution{public:boollemonadeChange......
  • 异步任务队列
    异步任务队列Task.WhenAll(List<Task>)等List中所有的异步任务完成后才算完成Task.WhenAny(List<Task>)List中某个完成就完成较常用的是Task.WhenAll(List<Task>)不aw......
  • 使用消息队列必须考虑的问题
    总结:为什么使用消息队列?异步、解耦、削峰。消息队列有什么缺点?可用性降低、系统复杂度提高、一致性问题。如何保证消息队列的可用性?镜像集群模式(RabbitMQ),主从......
  • rabbitmq 延时消息队列
    //rabbitmq延时消息队列生产端demo//1.将消息发送到延时交换机对应的队列上delay-queue,指定过期时间;过期后转发的交换机和绑定的key//2.过期时间过期......
  • 堆栈、队列、单调栈、单调队列1
    Stack和Queue——栈和队列栈的定义:栈是限定仅在表头进行插入和删除操作的线性表(先进后出)队列的定义:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)......
  • 代码随想录 |栈与队列总结篇
    基础知识:栈与队列都是容器接口,而非容器;栈与队列可选容器,缺省状态下是deque;提供push,pop等操作,但不提供送代器,不提供走访功能,因为只能在一边进行插入,弹出操作;栈的经典题......