(1)队列的基本概念

队头:允许删除元素的一端;

队尾:允许插入元素的一端。

2)队列的顺序存储结构

#include <stdio.h>
#define MaxSize 10
typedef struct SeQueue
{
    int data[MaxSize];
    int front,rear;
};
//初始化队列,队头、队尾指针均指0
void InitQueue(SeQueue &Q){
    Q.front=0;
    Q.rear=0;
}
//队列判空:队头与队尾指向相同空间,即差值为0,队空
bool QueueEmpty(SeQueue Q)
{
    return (Q.front==Q.rear);
}
//入队操作:先将数据插入至队尾,再将尾指针后移
bool EnQueue(SeQueue &Q,int x)
{
    if((Q.rear+1)%MaxSize==Q.front) return false; //判断队列是否满,满则返回false,这里牺牲了一个存储空间用来区分队满和队空
    Q.data[Q.rear]=x;
    Q.rear=(Q.rear+1)%MaxSize; //这里要注意!由于这种方式实现的队列在逻辑上似乎是循环的,也称作循环队列
    return true;
}
//出队操作:先将数据取出,再将头指针后移
bool DeQueue(SeQueue &Q,int &x)
{
    if(Q.front==Q.rear) return false; //判断是否队空
    x=Q.data[Q.front];
    Q.front=(Q.front+1)%MaxSize;
    return true;
}
//查;获取队头元素
bool GetHead(SeQueue Q,int &data)
{
    if(Q.front==Q.rear) return false;
    data=Q.data[Q.front];
    return true;
}
int main(void)
{
    SeQueue Q;
    int x;
    int data;
    InitQueue(Q);
    printf("队列是否为空:%d\n",QueueEmpty(Q));
    EnQueue(Q,1);
    printf("队列是否为空:%d\n",QueueEmpty(Q));
    GetHead(Q,data);
    printf("队头元素为:%d\n",data);
    DeQueue(Q,x);
    printf("队列是否为空:%d\n",QueueEmpty(Q));
    return 0;
}

队列元素个数:(Q.rear-Q.front+MaxSize)%MaxSize;

如果想要不浪费一个存储空间用来区分队满与队空,我们可以使用一个在队列中定义一个size用来记录元素个数,初始设为0,增加元素size++,减少元素size--,队满条件size= =Maxsize,队空条件为:size= =0;

也可以设置tag,删除tag置为0,插入tag置为1,队满一定是因为插入,tag一定为1;

3)队列的链式存储结构

#include <stdio.h>
#include <stdlib.h>
//定义链式队列结点
typedef struct LinkNode
{
    int data;
    LinkNode * next;
}LinkNode;
//定义链式队列
typedef struct 
{
    LinkNode * front,* rear;
}LinkQueue;
//初始化(带头结点)
void InitQueue(LinkQueue &Q)
{
    Q.front=Q.rear=(LinkNode *)malloc(sizeof(LinkNode)); 
    Q.front->next=NULL;
}
//队列判空:如果头、尾指针指向同一个结点或者头结点的next指向为NULL则为空
bool QueueEmpty(LinkQueue Q)
{
    return (Q.front->next==NULL);
    //return (Q.front=Q.rear);
}
//入队操作(带头结点)
void EnQueue(LinkQueue &Q,int x)
{
    //申请一个新的结点用于存储待插入的数据
    LinkNode * p=(LinkNode *)malloc(sizeof(LinkNode));
    p->data=x;
    //将新结点入队,即在队尾插入新结点
    p->next=NULL;
    Q.rear->next=p;
    Q.rear=p;
}
//出队操作(带头结点)
void DeQueue(LinkQueue &Q,int &x)
{
    LinkNode * p;
    p=Q.front->next;
    x=p->data;
    Q.front->next=p->next;
    //!!如果删除的元素为表尾结点,要将尾指针指向头结点
    if(Q.rear==p)Q.rear=Q.front;
    free(p);
}
//带头结点版本
int main(void)
{
    int x;
    LinkQueue Q;
    InitQueue(Q);
    printf("队列是否为空:%d\n",QueueEmpty(Q));
    EnQueue(Q,2);
    printf("队列是否为空:%d\n",QueueEmpty(Q));
    DeQueue(Q,x);
    printf("删除的元素为:%d\n",x);
    printf("队列是否为空:%d\n",QueueEmpty(Q));
    return 0;
}

#include <stdio.h>
#include <stdlib.h>
//定义链式队列结点
typedef struct LinkNode
{
    int data;
    LinkNode * next;
}LinkNode;
//定义链式队列
typedef struct 
{
    LinkNode * front,* rear;
}LinkQueue;
//初始化队列(不带头结点):使front、rear都指向NULL
void InitQueue1(LinkQueue &Q)
{
    Q.front=NULL;
    Q.rear=NULL;
}
//判断队列是否为空(不带头结点)
bool QueueEmpty1(LinkQueue Q)
{
    return (Q.front==NULL);
}
//入队操作(不带头结点)
void EnQueue1(LinkQueue &Q,int x)
{
    //申请一个结点用来存储入队数据
    LinkNode * p=(LinkNode *)malloc(sizeof(LinkNode));
    p->data=x;
    //执行入队操作
    p->next=NULL;
    if(Q.rear==NULL)
    {
        Q.front=p;
        Q.rear=p;
    }
    else
    {
        Q.rear->next=p;
        Q.rear=p;
    }
}
//出队操作(不带头结点)
void DeQueue1(LinkQueue &Q,int &x)
{
    LinkNode * p=Q.front;
    x=p->data;
    Q.front=p->next;
    //如果出队恰好使最后一个结点,那么要把rear恢复为NULL
    if(Q.rear==p)
        Q.rear=NULL;
    free(p);
}

int main(void)
{
    int x;
    LinkQueue Q;
    InitQueue1(Q);
    printf("队列是否为空:%d\n",QueueEmpty1(Q));
    EnQueue1(Q,2);
    printf("队列是否为空:%d\n",QueueEmpty1(Q));
    DeQueue1(Q,x);
    printf("删除的元素为:%d\n",x);
    printf("队列是否为空:%d\n",QueueEmpty1(Q));
    return 0;
}