队列

队列

是一种先进先出线性表,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和主存

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

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

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

posted @ 2023-02-01 23:30  原语  阅读(50)  评论(0编辑  收藏  举报