队列和栈相反,队列是一种先进先出(First In First Out,简称FIFO)的线性表,它只允许在表的一段进行插入,另一端进行删除。
队列因为要涉及到头删和尾插,那么使用链式结构效率会相对高一点。本篇文章的实现方式采用链式队列。
队列的只需要入队和出队操作,即头删和尾插,那么我们定义一个头指针(head)和一个尾指针(tail)。但是这里如果定义两个数据的话,我们传参的时候就会非常的麻烦,所以我们用结构封装起来。
tips:
为什么同样是链式结构,为什么单链表不设计尾指针呢?
- 因为单链表还要涉及到尾删和中间位置删除,这样就算定义了尾指针,我们还是需要遍历链表,找到删除位置前一个节点,所以没有太大的必要。
- 而这里只是需要进行尾插操作,那么我们定义一个尾指针会很舒服,尾插的时候不需要遍历链表。
#pragma once
#include
#include
#include
#include
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
//初始化
void QueueInit(Queue*pq);
//销毁
void QueueDestroy(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//入队
void QueuePush(Queue* pq, QDataType data);
//出队
void QueuePop(Queue* pq);
//获取队尾元素
QDataType QueueBack(Queue* pq);
//获取对头元素
QDataType QueueFront(Queue* pq);
//获取有效元素个数
int QueueSize(Queue* pq);
//初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
//销毁
void QueueDestroy(Queue* pq)
{
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
//判空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size == 0;
}
//入队
void QueuePush(Queue* pq, QDataType data)
{
//尾插
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = data;
newnode->next = NULL;
if (pq->head == NULL)
{
assert(pq->tail == NULL);
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
//出队
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
//头删
if (pq->head->next == NULL)//只剩最后一个节点
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* newhead = pq->head->next;
free(pq->head);
pq->head = newhead;
}
pq->size--;
}
//获取队尾元素
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
//获取对头元素
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
//获取有效元素个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:6031)
#include"Queue.h"
void TestQueue1()
{
Queue q;
//初始化测试
QueueInit(&q);
//入队测试
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePush(&q, 5);
QueuePush(&q, 6);
QueuePush(&q, 7);
int size = QueueSize(&q);
//获取队尾元素测试
printf("%d\n", QueueBack(&q));
while (size--)
{
//获取队头元素测试
printf("%d ", QueueFront(&q));
//出队测试
QueuePop(&q);
}
//销毁测试
QueueDestroy(&q);
}
int main()
{
TestQueue1();
return 0;
}