百度定义
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
举个例子
学生排队买饭。有什么特点呢?当然,你先来,就先打饭,先吃饭。抽象到队列上说,有队头,队尾,要想加入(入队),只能从队尾加,想走(出队),只能从队头走。即:先进先出。
和栈一样,它常见的两种存储是顺序存储和链式存储。
顺序存储结构
用顺序存储时,会遇到这样的情况,数组并没有满,却入不了队(假溢出),原因在于队头没有在数组的0下标处。一般情况下,因为队列会存在假溢出的情况,所以采用循环队列。
定义
#define MAX
typedef struct
{
int date[MAX];
int rear; //控制队尾
int front;//控制队头
int count;
}CirQueue;
初始化
void InitQueue(CirQueue *Q)
{
Q->front = Q->rear = 0;
Q->count = 0;//计数器置0
}
判空
int QueueEmpty(CirQueue *Q)
{
return Q->count == 0;//队列无元素为空
}
判满
int QueueFull(CirQueue *Q)
{
return Q->count == Max;//队中元素个数等于max时队满
}
入队列
void EnQueue(CirQueuq *Q,int x)
{
if(QueueFull((Q)) {
Error("Queue overflow");//队列满了
}
Q->count++;//队列元素个数加1
Q->data[Q->rear] = x;//新元素插入队尾
Q->rear = (Q->rear + 1) % Max;//用的是循环,当满时头尾相差一个空间,用于区别满和不满。
}
出队列
DataType DeQueue(CirQueue *Q)
{
int temp;
if(QueueEmpty((Q)) {
Error("QueueEmpty"); //队空
}
temp = Q->data[Q->front];
Q->count--;//队列元素个数减1
Q->front = (Q->front + 1) % Max; //循环意义下的头指针加1
return temp;
}
取队头元素
int QueueFront(CirQueue *Q)
{
if(QueueEmpty(Q)) {
Error("Queue if empty.");
}
return Q->data[Q->front];
}
链式存储结构
定义
typedef struct Queue//结点结构
{
int data;
struct Queue *next;
} Queue;
typedef struct //队列的链表结构
{
Queue *front; //队头、队尾指针
Queue *rear;
} LinkQueue;
初始化
LinkQueue *InitQueue(LinkQueue *q)
{
q->front = q->next =(Queue*)malloc(sizeof(Queue));
q->front->next = NULL;
return q;
}
判空
int QueueEmpty(CirQueue *Q)
{
if(q->front == q->rear){
return 1;
}
return 0;
}
入队列
LinkQueue *EnQueue(LinkQueue *q, int e)
{
Queue *p = (Queue*)malloc(sizeof(Queue));//为插入节点分配空间
if(!p) {
//分配空间失败
cout<<"not enough memory!"<<endl;
}
else {
//建节点
p->data = e; //为插入节点数据域赋值
p->next = NULL;//为插入节点指针域赋值
//实现插入
q->rear->next = p;//插入到队尾
q->rear = p;//队尾指针重新指向新任队尾
}
return q;
}
元素出队
LinkQueue *DeQueue(LinkQueue *q)
{
Queue *p;
if(q->front == q->rear) {
cout<<"LinkQueue is NULL"<<endl;
}
else {
p = q->front->next;//将欲删除的队头结点暂存给p
int e = p->data;//把队头数据赋给e
cout<<"delete: "<<e<<endl;
q->front->next = p->next;//删除,将原队头结点的后继p->next赋值给头结点后继
if(q->rear == p) {
//若队头就是队尾,则删除后将rear指向头结点
cout<<"链队列数据全部删除完毕!"<<endl;
q->rear = q->front;
}
free(p);
}
return q;
}
返回头元素
void GetQHead(LinkQueue *q)
{
Queue *p;
if(q->front == q->rear) {
cout<<"LinkQueue is NULL"<<endl;
}
else {
p = q->front->next;//队头
cout<<"队头元素:"<<p->data<<endl;
}
}
求队列长度
int QueueLength(LinkQueue *q)
{
int length = 0;
Queue *p;
p = q->front->next;//队头
while(p) {
length++;
p = p->next;
}
return length;
}
以上,欢迎留言交流~