目录
1.1 队列的概念及结构
只允许在一端进行插入数据操作,而在另一端进行删除数据操作的特殊的线性表,队列具有先进先出的特性。
入队列:进行插入数据操作的一端叫做队尾。
出队列:进行删除数据操作的一端叫做队头。
结构示意图如下:
1.2 构造队列
通过链式结构表示队列
typedef int QDataType;
//链式结构:表示队列
typedef struct QueueNode {
QueueNode* next;
QDataType data;
}QNode;
由于队列需要在队头和队尾两端进行不同的操作,所以队列本身应包含队头和队尾。
此时,构造队列的结构
//队列的结构
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
1.3 初始化队列
void QInit(Queue* pq) {
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
1.4 毁坏队列的所有节点
void QDestroy(Queue* pq) {
assert(pq);
QNode* cur = pq->head;
while (cur) {
QNode* next = cur->next;
free(next);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
此处需要注意:构成队列的节点的结构体是QNode, 表明队列性质(即队头删除、队尾插入)的结构体(head、tail、size)是Queue。
如下图所示:
1.5 在队尾插入数据
void QPush(Queue* pq, QDataType x) {
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode = NULL) {
perror("malloc fail");
return;
}
//为新节点赋值x
newnode->data = x;
newnode->next = NULL;
//将新节点链接到队尾
if (pq->head == NULL) {
pq->head = pq->tail = newnode;
}
else {
pq->tail->next = newnode;
pq->tail = pq->tail->next;
}
pq->size++;
}
1.6 在队头删除数据
void QPop(Queue* pq) {
//进行断言
assert(pq);
//删除时头不能为空
assert(pq->head != NULL);
//进行删除
QNode* hnext = pq->head->next;
//首先,若只剩下一个节点时:
if (hnext == NULL) {
pq->head = pq->tail = NULL;
}
else {
free(pq->head);
pq->head = hnext;
}
pq->size--;
}
1.7 返回队列的节点数、判断队列是否为空
int QSize(Queue* pq) {
assert(pq);
return pq->size;
}
bool QEmpty(Queue* pq) {
assert(pq);
return pq->size == 0;
}
1.8 返回队首数据和队尾数据
QDataType QFront(Queue* pq) {
assert(pq);
assert(!QEmpty(pq));
return pq->head->data;
}
QDataType QBack(Queue* pq) {
assert(pq);
assert(!QEmpty(pq));
return pq->tail->data;
}
1.9 运行测试(在Visual Studio上运行)
头文件(Queue.h)
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDataType;
//链式结构:表示队列
typedef struct QueueNode {
struct QueueNode* next;
QDataType data;
}QNode;
//队列的结构
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
void QInit(Queue* pq);
void QDestroy(Queue* pq);
void QPush(Queue* pq,QDataType x);
void QPop(Queue* pq);
int QSize(Queue* pq);
bool QEmpty(Queue* pq);
QDataType QFront(Queue* pq);
QDataType QBack(Queue* pq);
源文件1(Queue.c)
#include"Queue.h"
void QInit(Queue* pq) {
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QDestroy(Queue* pq) {
assert(pq);
QNode* cur = pq->head;
while (cur) {
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QPush(Queue* pq, QDataType x) {
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL) {
perror("malloc fail");
return;
}
//为新节点赋值x
newnode->data = x;
newnode->next = NULL;
//将新节点链接到队尾
if (pq->head == NULL) {
pq->head = pq->tail = newnode;
}
else {
pq->tail->next = newnode;
pq->tail = pq->tail->next;
}
pq->size++;
}
void QPop(Queue* pq) {
//进行断言
assert(pq);
//删除时头不能为空
assert(pq->head != NULL);
//进行删除
QNode* hnext = pq->head->next;
//首先,若只剩下一个节点时:
if (hnext == NULL) {
pq->head = pq->tail = NULL;
}
else {
free(pq->head);
pq->head = hnext;
}
pq->size--;
}
int QSize(Queue* pq) {
assert(pq);
return pq->size;
}
bool QEmpty(Queue* pq) {
assert(pq);
return pq->size == 0;
}
QDataType QFront(Queue* pq) {
assert(pq);
assert(!QEmpty(pq));
return pq->head->data;
}
QDataType QBack(Queue* pq) {
assert(pq);
assert(!QEmpty(pq));
return pq->tail->data;
源文件2(Test.c)
#include"Queue.h"
int main() {
Queue p;
QInit(&p);
QPush(&p, 1);
QPush(&p, 2);
QPush(&p, 3);
QPush(&p, 4);
while (!QEmpty(&p)) {
printf("%d ", QFront(&p));
QPop(&p);
}
printf("\n");
QDestroy(&p);
return 0;
}
运行结果: