队列也是一种特殊的线性表,线性表允许在任意位置进行插入和删除操作,而队列只允许在一端进行插入操作(入队列),而另一端进行删除操作(出队列)。
进行插入操作的端称为队尾,进行删除操作的一端称为队头。队列中没有数据元素时称为空队列。
队头和队尾分别由队头指示器(队头指针)和队尾指示器(队尾指针)指向。
所以队列是一种先进先出表(first in first out),也称FIFO表。
/*初始化链式队列*/
void QueueInit(q);
/*判断队列是否非空,非空返回1,空返回0*/
int QueueNotEmpty(q);
/*元素x入队列*/
void QueueAppend(q,x);
/*出队列,元素保存在x中,成功返回1,失败返回0*/
int QueuePop(q, x);
/*取队头元素,保存在x中,成功返回1,失败返回0*/
int QueueGet(q, x);
用一片连续的存储空间来存储队列中的数据元素,这样的队列称为顺序队列。
但是顺序队列存在“假溢出”现象,即当队列满之后,队尾指针指向最后一个元素空间,表示队列已满。出队列一个元素后,此时队列应该不为队满状态,但是队尾指针仍然指向最后一个元素空间,表示队列已满。解决“假溢出”现象可以用顺序循环队列。
顺序循环队列可以解决假溢出的情况,但是存在队空、队满的判断条件都是rear= =front的情况
解决顺序循环队列队空、队满状态判断有三种实现形式:
其实计数器是标志位的一个升级版,也可之间把count当标志位用
因此下方给出少用一个储存空间和设置计数器两种代码实现。
代码实现:
//#pragma once //作为头文件时加上这行
#include
#include
#include
#define MAXSIZE 50
#define DataType char
typedef struct {
DataType queue[MAXSIZE];
int rear;
int front;
}SeqQueue;
void QueueInit(SeqQueue* q);
int QueueNotEmpty(SeqQueue* q);
int QueueAppend(SeqQueue* q, DataType x);
int QueuePop(SeqQueue* q, DataType *x);
int QueueGet(SeqQueue* q, DataType *x);
void QueueInit(SeqQueue* q)
{
q->rear = 0;
q->front = 0;
}
int QueueNotEmpty(SeqQueue* q)
{
if (q->rear != q->front)return 1;
else return 0;
}
int QueueAppend(SeqQueue* q, DataType x)
{
if ((q->rear + 1) % MAXSIZE == q->front) {
printf("队列已满,无法插入\n");
return 0;
}
q->queue[q->rear] = x;
q->rear = (q->rear + 1) % MAXSIZE;
return 1;
}
int QueuePop(SeqQueue* q, char *x)
{
if (QueueNotEmpty(q)) {
*x = q->queue[q->front];
q->front = (q->front + 1) % MAXSIZE;
return 1;
}
printf("队列中元素为空,无元素出队列\n");
return 0;
}
int QueueGet(SeqQueue* q, char *x)
{
if (QueueNotEmpty(q)) {
*x = q->queue[q->front];
return 1;
}
printf("队列中元素为空,无元素可取\n");
return 0;
}
代码实现:
/#pragma once //作为头文件时加上这行
#include
#include
#include
#define DataType char
#define QUEUE_MAXSIZE 30
typedef struct {
DataType queue[QUEUE_MAXSIZE];
int rear;
int front;
int count;
}SeqQueue;
void QueueInit(SeqQueue* q);
int QueueNotEmpty(SeqQueue* q);
int QueueAppend(SeqQueue* q, DataType x);
int QueuePop(SeqQueue* q, DataType *x);
int QueueGet(SeqQueue* q, DataType *x);
void QueueInit(SeqQueue* q)
{
q->rear = 0;
q->front = 0;
q->count = 0;
}
int QueueNotEmpty(SeqQueue* q)
{
if (q->count != 0)return 1;
else return 0;
}
int QueueAppend(SeqQueue* q, DataType x)
{
if (q->count == QUEUE_MAXSIZE) {
printf("队列已满,无法插入\n");
return 0;
}
q->queue[q->rear] = x;
q->count++;
q->rear = (q->rear + 1) % QUEUE_MAXSIZE;
return 1;
}
int QueuePop(SeqQueue* q, DataType *x)
{
if (QueueNotEmpty(q)) {
*x = q->queue[q->front];
q->count--;
q->front = (q->front + 1) % QUEUE_MAXSIZE;
return 1;
}
printf("队列中元素为空,无元素出队列\n");
return 0;
}
int QueueGet(SeqQueue* q, DataType *x)
{
if (QueueNotEmpty(q)) {
*x = q->queue[q->front];
return 1;
}
printf("队列中元素为空,无元素可取\n");
return 0;
}
测试函数:
void test()
{
char c;
SeqQueue q;
QueueInit(&q); //初始化队列
//入队列
QueueAppend(&q, 'T');
QueueAppend(&q, 'h');
QueueAppend(&q, 'i');
QueueAppend(&q, 's');
QueueAppend(&q, ' ');
QueueAppend(&q, 'a');
QueueAppend(&q, ' ');
QueueAppend(&q, 't');
QueueAppend(&q, 'e');
QueueAppend(&q, 's');
QueueAppend(&q, 't');
//出队列,并输出。
while (QueueNotEmpty(&q))
{
QueueGet(&q, &c);
printf("%c ", c);
QueuePop(&q, &c);
}
}
代码实现:
//#pragma once //作为头文件时加上这行
#include
#include
#include
#define DataType char
/*链式队列中结点的结构体定义*/
typedef struct queue_node{
DataType data;
struct queue_node* next;
}queue_node;
/*链式队列结构体*/
typedef struct {
queue_node *front; //队头指针
queue_node *rear; //队尾指针
}LinkedQueue;
/*初始化链式队列*/
void QueueInit(LinkedQueue* q);
/*判断队列是否非空,非空返回1,空返回0*/
int QueueNotEmpty(LinkedQueue* q);
/*元素x入队列*/
void QueueAppend(LinkedQueue* q, DataType x);
/*出队列,元素保存在x中,成功返回1,失败返回0*/
int QueuePop(LinkedQueue* q, DataType *x);
/*取队头元素,保存在x中,成功返回1,失败返回0*/
int QueueGet(LinkedQueue* q, DataType *x);
/*撤销队列结点的内存*/
void QueueDestroy(LinkedQueue* q);
void QueueInit(LinkedQueue* q)
{
q->front = NULL;
q->rear = NULL;
}
int QueueNotEmpty(LinkedQueue* q)
{
if (q->front != NULL)return 1;
else return 0;
}
void QueueAppend(LinkedQueue* q, DataType x)
{
queue_node *p = (queue_node *)malloc(sizeof(queue_node));
p->data = x;
p->next = NULL;
if (q->rear != NULL)q->rear->next = p; //队列原来非空时,队尾加新结点
q->rear = p; //修改队尾指针
if (q->front == NULL)q->front = p; //队列原来为空是,修改队头指针
}
int QueuePop(LinkedQueue* q, DataType *x)
{
queue_node *p = NULL;
if (q->front==NULL) {
printf("队列中元素为空,无元素出队列\n");
return 0;
}
*x = q->front->data;
p = q->front;
q->front = p->next; //出队列结点脱离队列
if (q->front == NULL)q->rear = NULL; //删除最后一个结点时要置队尾指针为空
free(p);
return 1;
}
int QueueGet(LinkedQueue* q, DataType *x)
{
if (q->front == NULL) {
printf("队列中元素为空,无元素可取\n");
return 0;
}
*x = q->front->data;
return 1;
}
void QueueDestroy(LinkedQueue* q)
{
queue_node *p1 = NULL, *p2 = NULL;
p1 = q->front;
while (p1 != NULL)
{
p2 = p1;
p1 = p1->next;
free(p2);
}
}
测试函数:
void test()
{
char c;
LinkedQueue q;
QueueInit(&q); //初始化队列
//入队列
QueueAppend(&q, 'T');
QueueAppend(&q, 'h');
QueueAppend(&q, 'i');
QueueAppend(&q, 's');
QueueAppend(&q, ' ');
QueueAppend(&q, 'a');
QueueAppend(&q, ' ');
QueueAppend(&q, 't');
QueueAppend(&q, 'e');
QueueAppend(&q, 's');
QueueAppend(&q, 't');
//出队列,并输出。
while (QueueNotEmpty(&q))
{
QueueGet(&q, &c);
printf("%c ", c);
QueuePop(&q, &c);
}
}
运行结果: