队列

队列是只允许在一端进行插入操作而在另一端进行删除操作的线性表。

队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。假设队列是q=(a1,a2,……,an),那么a1就是队头元素而an就是队尾元素。这样我们就可以删除时总是从a1开始而插入时列在最后。

一、循环队列定义:

    和顺序栈类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元依次存放从队列头到队列尾的元素外,尚需附设两个指针front和rear分别指示队列头元素及队列尾元素的下一位置。约定:初始化建空队列时,令front=rear=0,每当插入新的队列元素时,“尾指针增1”;每当删除队列头元素时“头指针增1”。把队列头尾相接的顺序存储结构称为队列。

  若队列的最大尺寸为QueueSize,那么队列满的条件是(rear + 1)%QueueSize == front

  通用的计算队列长度公式为:(rear - front + QueueSize)%QueueSize

循环队列的顺序存储结构:

#define MAXSIZE 100
typedef struct
{
    int data[MAXSIZE];
    int front;    //头指针
    int rear;    //尾指针 ,若队列不为空,指向队列尾元素的下一个位置
}SqQueue;

循环队列初始化 求长度 插入 删除

//循环队列初始化
void InitQueue(SqQueue *Q)
{
    Q->front = 0;
    Q->rear = 0;
}

//循环队列求队列长度
int QueueLength(SqQueue Q)
{
    return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}

//循环队列入队列 若队列未满,则插入元素e为Q新的队尾元素。
void EnQueue(SqQueue *Q, int e)
{
    if ((Q->rear + 1) % MAXSIZE == Q->front) //队列满
        return; 

    Q->data[Q->rear] = e; //将元素e赋给队尾
    Q->rear = (Q->rear + 1) % MAXSIZE; //rear 指针向后移一位置
                                      //若到最后则转到数组头部
}

//循环队列出队列 若队列不为空,则删除Q中的队头元素,用e返回其值
int DeQueue(SqQueue *Q, int *e)
{
    if (Q->front == Q->rear) //队列空
        return 0;
    *e = Q->data[Q->front]; //将队列头元素赋值给e
    Q->front = (Q->front + 1) % MAXSIZE; //front指针后移一位
                                         //若到最后则转到数组头部
    return *e;
}

二、

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

为了操作方便,将队头指针指向队列的头结点,而队尾指针指向终端结点。

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

队列的链式存储结构:

typedef struct QNode
{
    int data;
    struct QNode *next;
}QNode;

typedef struct
{
    QNode *front, *rear;
}LinkQueue;

入队

  就是在链表尾部插入结点

LinkQueue *insert(LinkQueue *Q, int x)
{
    QNode *s = (QNode *)malloc(sizeof(QNode)); //头结点
    if (!s)
        exit(0);
    s->data = x;
    s->next = NULL;

    if (Q->rear == NULL) //空队列
    {
        Q->front = s;
        Q->rear = s;
    }
    else
    {
        Q->rear->next = s;
        Q->rear = s; //把当前s设置为队尾结点 rear指向s
    }
    return (Q);
}

出队

  就是头结点的后继结点出队,将头结点的后继改为它后面的结点。若链表除头结点外只剩一个元素时则只需将rear指向头结点。

int del(LinkQueue *Q)
{
    QNode *p;int x;
    if (Q->front == Q->rear) //头指针和尾指针均指向头结点
        printf("
  empty Queue;");
    p = Q->front->next; //将欲删除的队头结点暂存给p
    x = p->data;

    Q->front->next = p->next; //将原队头结点后继p->next赋值给头结点后继
    if (Q->rear == p)    //若队头结点是队尾,则删除后将rear指向头结点
        Q->rear = Q->front;
    free(p);
    return x;
}
原文地址:https://www.cnblogs.com/Yang-Xin-Yi/p/14665263.html