队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头。
队列的实现
队列与栈相似,都可以使用链表和数组来组成。但是与栈不同的是,如果使用数组来实现的话,由于队列是先进先出的结构,在以数组作为基础结构时出队列会非常的麻烦,需要移动整个数组的元素。因此使用链表来作为队列的基础结构。
队列的结点以及队列的指针
//数据类型
typedef int QDataType;
//队列的结点
typedef struct QueueNode
{
QDataType _data;
struct QueueNode* _next;
}QNode;
//队列的处于入的指针
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
队列的初始化
//队列初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
pq->size = 0;
}
队列的销毁
//队列销毁
void QueueDestory(Queue* pq)
{
assert(pq);
while (pq->head != NULL)
{
QNode* del = pq->head;
pq->head = pq->head->_next;
free(del);
}
pq->head = NULL;
pq->tail = NULL;
pq->size = 0;
}
在队列的销毁中,需要注意的是当队列的元素全部销毁时,要将尾指针和头指针都指向空结点并且将大小归零。
入队列
//入队列
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
if (pq->head == NULL)
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc failed");
exit(-1);
}
newnode->_data = x;
pq->head = newnode;
pq->tail = newnode;
pq->tail->_next = NULL;
}
else
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc failed");
exit(-1);
}
newnode->_data = x;
pq->tail->_next = newnode;
pq->tail = pq->tail->_next;
pq->tail->_next = NULL;
}
pq->size++;
}
在这里使用的头结点与尾节点都是看做没有带哨兵位的指针。在入队列的时候需要分第一次入队与其他的情况。
出队列
//出队列
void QueuePop(Queue* pq)
{
assert(pq);
//assert(pq->head != NULL);
assert(!QueueEmpty(pq));
Queue* del = pq->head;
pq->head = pq->head->_next;
free(del);
if (pq->head == NULL)
{
pq->tail = NULL;
}
pq->size--;
}
出队列也需要注意尾指针的问题。
队列的首元素
//队列首元素
QDataType QueueFront(Queue* pq)
{
assert(pq);
//assert(pq->head != NULL);
assert(!QueueEmpty(pq));
return pq->head->_data;
}
队列的尾元素
//队列尾元素
QDataType QueueBack(Queue* pq)
{
assert(pq);
//assert(pq->head != NULL);
assert(!QueueEmpty(pq));
return pq->tail->_data;
}
队列是否为空
//队列是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL && pq->tail == NULL;
}
队列的元素个数
//队列元素个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
附录
//Queue.c
#include "Queue.h"
//队列初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
pq->size = 0;
}
//队列销毁
void QueueDestory(Queue* pq)
{
assert(pq);
while (pq->head != NULL)
{
QNode* del = pq->head;
pq->head = pq->head->_next;
free(del);
}
pq->head = NULL;
pq->tail = NULL;
pq->size = 0;
}
//入队列
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
if (pq->head == NULL)
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc failed");
exit(-1);
}
newnode->_data = x;
pq->head = newnode;
pq->tail = newnode;
pq->tail->_next = NULL;
}
else
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc failed");
exit(-1);
}
newnode->_data = x;
pq->tail->_next = newnode;
pq->tail = pq->tail->_next;
pq->tail->_next = NULL;
}
pq->size++;
}
//出队列
void QueuePop(Queue* pq)
{
assert(pq);
//assert(pq->head != NULL);
assert(!QueueEmpty(pq));
Queue* del = pq->head;
pq->head = pq->head->_next;
free(del);
if (pq->head == NULL)
{
pq->tail = NULL;
}
pq->size--;
}
//队列首元素
QDataType QueueFront(Queue* pq)
{
assert(pq);
//assert(pq->head != NULL);
assert(!QueueEmpty(pq));
return pq->head->_data;
}
//队列尾元素
QDataType QueueBack(Queue* pq)
{
assert(pq);
//assert(pq->head != NULL);
assert(!QueueEmpty(pq));
return pq->tail->_data;
}
//队列是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL && pq->tail == NULL;
}
//队列元素个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//Queue.h
#pragma once
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <stdlib.h>
//数据类型
typedef int QDataType;
//队列的结点
typedef struct QueueNode
{
QDataType _data;
struct QueueNode* _next;
}QNode;
//队列的处于入的指针
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
//队列初始化
void QueueInit(Queue* pq);
//队列销毁
void QueueDestory(Queue* pq);
//入队列
void QueuePush(Queue* pq, QDataType x);
//出队列
void QueuePop(Queue* pq);
//队列首元素
QDataType QueueFront(Queue* pq);
//队列尾元素
QDataType QueueBack(Queue* pq);
//队列是否为空
bool QueueEmpty(Queue* pq);
//队列元素个数
int QueueSize(Queue* pq);
//test.c
#include "Queue.h"
void TestQueue1()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
printf("%d ", QueueFront(&q));
printf("%d ", QueueBack(&q));
printf("%d ", QueueSize(&q));
printf("%d ", QueueEmpty(&q));
QueuePop(&q);
QueuePop(&q);
QueuePop(&q);
printf("%d ", QueueFront(&q));
printf("%d ", QueueBack(&q));
printf("%d ", QueueSize(&q));
printf("%d ", QueueEmpty(&q));
printf("\n");
QueuePop(&q);
printf("%d ", QueueSize(&q));
printf("%d ", QueueEmpty(&q));
QueueDestory(&q);
}
int main()
{
TestQueue1();
return 0;
}
本文暂时先叙述到这里,在之后的文章中我们介绍几道与栈和队列的题目。