队列简介
队列只允许在队列头进行删除操作,在队列尾进行插入操作,当队列中没有元素时,称为空队列。在队列中插入元素称为入队,从队列中删除元素称为出队。因为队列只允许在尾端插入,在头端删除,所以只有最早进入队列的元素才能最先从队列中删除,即队列有 先进先出 的特点。
- 队列是一种操作受限的线性表,队列只允许在表的一端进行插入,在表的另一端进行删除。可进行插入的一段称为队尾,可进行删除的一端称为队头。
- 队列的主要特点就是先进先出。依照存储结构可分为:顺序队和链式队。
队列的特点
-
队列为一种特殊的线性表,
-
表的前端(front)进行删除操作,在表的后端(rear)进行插入操作,
-
进行插入操作的端称为队尾,进行删除操作的端称为队头
-
队列中没有元素时,称为空队列。
-
队列的数据元素又称为队列元素
-
在队列中插入一个队列元素称为入队
-
从队列中删除一个队列元素称为出队
-
因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出
顺序队列
即仅在队头进行删除在队尾进行插入,可用地址连续的存储单元依次存放队列中的数据,比如数组。队头和队尾的位置是变化的,所以要设置头、尾指针。
初始化时的头尾指针,均置为 0。 当头尾指针相等时队列为空或者为满,在非空队列里,头指针始终指向队头元素,尾指针始终指向队尾元素的下一位置。
由队列的原理可以将头指针当做读操作,将尾指针当做写操作,即在尾端插入数据就是写入队列,在头端删除数据就是将队列中的数据读出,这样好理解点。
刚开始头指针和尾指针都在同一位置
当队列入队时,尾指针加一,头指针保持不变,a1入队,尾指针rear+1指向下一个地址空间,即尾指针始终指向队尾的下一地址,如a4入队后,尾指针rear+1 。
队列出队时,尾指针保持不变,头指针依次加1,由先进先出原则,a1先入队,则a1先被读走,然后front+1,指向了 a2,a2删除后,front+1指向了 a3。
a5删除后,头指针和尾指针的指向又相同相等了,即说明队列中的数据 已经全部读走
在顺序队列中,当尾指针已经指向了队列的最后一个位置的下一位置时,如果再有元素入队,就会发生“溢出”,此时队列中已经填满了数据,头指针还在开始位置。
顺序队列的 “假溢出” :即队列的存储空间并未填满,却发生了溢出。
比如 rear 现在指向了最后一个位置的下一位置,按照上面所说此时队列已经被填满,如果再有元素入队,就会发生“溢出”,但这是在头指针没有移动的前提下,如果之前队列头也删除了一些元素,那么队列头指针经过n次的 +1 之后,会遗留下了很多空地址,但是顺序队列就会认为再有元素入队,就溢出,即出现 “假溢出” 现象,这是不合理的。
其实就是类似与尾插法,和栈的差别可以简单的理解为:
- 插入方式不同,一个类似与头插法,一个类似于尾插法
- 弹出方式的话,这两个其实差不多,基本可以用相同的方法实现
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
} Node;
Node* initQueue()
{
Node* node = (Node*)malloc(sizeof(Node));
node->data=0;
node->next=NULL;
return node;
}
/*
插入步骤,类似与尾插法
*/
void enQueue(Node* list, int data)
{
Node* node = (Node*)malloc(sizeof(Node));
Node* head = list;
node->data=data;
while(list->next)list=list->next;
node->next=list->next;
list->next=node;
head->data++;
}
/*
判断数据是否为空
*/
int isEmpty(Node* list)
{
if(list->data)
return 1;
else
return 0;
}
/*
弹出数据,数据先进先出,后进后出
*/
int deQueue(Node* list)
{
int data;
if(isEmpty(list))
{
Node* head = list;
Node* node = list->next;
data = node->data;
list->next=node->next;
free(node);
head->data--;
return data;
}
else
return EOF;
}
void printQueue(Node* Q)
{
Node* node = Q -> next;
while (node)
{
printf("%d -> ", node -> data);
node = node -> next;
}
printf("NULL\n");
}
int main()
{
Node* Q = initQueue();
enQueue(Q, 1);
enQueue(Q, 2);
enQueue(Q, 3);
enQueue(Q, 4);
printQueue(Q);
printf("dequeue = %d\n", deQueue(Q));
printf("dequeue = %d\n", deQueue(Q));
printQueue(Q);
return 0;
}
往期回顾
1.【第一章】《线性表与顺序表》
2.【第一章】《单链表》
3.【第一章】《单链表的介绍》
4.【第一章】《单链表的基本操作》
5.【第一章】《单链表循环》
6.【第一章】《双链表》
7.【第一章】《双链表循环》
8.【第二章】《栈》