队列是只能在表的一端进行插入,在另一端进行删除操作的线性表
允许删除元素的一端称为队头,允许插入元素的另一端称为队尾
先进先出表 First in First out (FIFO)
队列有两个活动端:设置了队头(front)和队尾(rear)两个位置的指针
front和rear指针分别是队头和队尾的下标值
本章仅讨论队列顺序存储的方式
队列的应用:计算机缓存
顺序表中,每删除一个元素,此后所有元素依次向前移动,在顺序存储的队列中,每次出队列的元素必是队头元素,效率低下
入队和出队都是移动指针,不移动元素
入队:指针rear先向前移动一步,将新元素在rear位置插入
出队:指针front先向前移动一步,将下标为front的元素取出
由于rear和front指针只能单方向移动,最终rear和front指针指向数组的最大下标位置,当入队出队操作反复执行时会产生“假溢出”
解决方法:循环队列:采用数学方法将rear和front指针从数组空间最大下标位置移到最小下标位置
数组空间长度M
%求余
//入队
rear=(rear+1)%M;
//出队
front=(front+1)%M;
//队空
front==rear;
//队满
(rear+1)%M=front;
为了判断队列是空还是满,一般将头指针front指向的空间舍弃
循环队列结构体类型描述
typedef struct QUEUE
{
DataType* queArray; //存放元素的数组指针
int front; //队头
int rear; //队尾
int maxLength; //队列的最大容量
}Queue;
创建一个队列
C语言 strlen 函数用来求字符串的长度(包含多少个字符)
char是1字节
sizeof 统计出的字符串长度比 strlen() 函数的统计值大 1
原因很简单,sizeof 统计了字符串结尾的\0
,而 strlen() 函数没有
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h> //函数strlen() 不计\0
#include<iostream>
using namespace std;
typedef char DataType; //将char重定义为DataType
typedef struct QUEUE //queue队列
{
DataType* queArray; //存放元素的数组指针queArray
int front; //队头front
int rear; //队尾rear
int maxLength; //队列的最大容量maxLength
}Queue;
//创建一个队列
Queue* CreatQueue(int length) //最大长度
{
Queue* queue = (Queue*)malloc(sizeof(Queue)); //结构体Queue
if (queue)
{
//申请内存
queue->queArray = (DataType*)malloc(sizeof(Queue));
//失败则返回NULL
if (queue->queArray == NULL)
{
return NULL;
}
queue->front = 0; //清空队列
queue->rear = 0; //清空队列
//记录最大容量
queue->maxLength = length;
}
return queue; //返回指向队列的指针queue
}
//销毁队列
void DestoryQueue(Queue* queue)
{
free(queue->queArray); //free()
free(queue);
}
//清空队列
void ClearQueue(Queue* queue)
{
queue->front = 0; //清空队列
queue->rear = 0; //清空队列
}
//得到队列的长度
int GetQueueLength(Queue* queue)
{
int length;
if (queue->rear >= queue->front) //队尾>队头
{
length = queue->rear - queue->front;
}
else //队尾<队头
{
length = queue->rear - queue->front + queue->maxLength;
}
return length;
}
//入队
void EnQueue(Queue* queue, DataType data)
{
if ((queue->rear + 1) % queue->maxLength == queue->front) //判断队列是否已满
{
printf("队列已满");
}
else
{
//队尾向后移动一位
queue->rear = (queue->rear + 1) % queue->maxLength; //%取余
//入队
queue->queArray[queue->rear] = data; //插入
}
}
//出队,仅仅移动队头即可
DataType OutQueue(Queue* queue)
{
if (GetQueueLength(queue) > 0) //判断队为非空
{
queue->front = (queue->front + 1) % queue->maxLength; //queue->front向后移动一位
return queue->queArray[queue->front]; //取出queue->front位置的值
}
else //队为空
{
return 0;
}
}
//取队头元素
DataType GetQueueHead(Queue* queue)
{
if (GetQueueLength(queue) > 0) //队为非空
{
int k = (queue->front + 1) % queue->maxLength; //头元素下标
return queue->queArray[k];
}
else
{
return 0; //队是空的,返回0
}
}
//主函数
int main()
{
const int QueueMax = 100; //定义队列最大容量
//创建队列
Queue* queue = CreatQueue(QueueMax);
if (queue == NULL)
{
return 1;
}
printf("连续输入不超过十个字符作为入队列字符");
char ch[10];
(void)scanf("%s", &ch);
for (int i = 0; i < strlen(ch); i++)
{
EnQueue(queue, ch[i]);
}
printf("字符出队顺序为:");
//所有元素依次出队直到队空
while (GetQueueLength(queue) > 0) //判断非空队列
{
printf("出队:%c\n", OutQueue(queue));
}
DestoryQueue(queue);
return 0;
}