目录
写在最前的话
数据结构的实现不是单一的或者统一的,思想是关键,代码实现的细节的差异因人而异,使用数据结构应当对代码进行了解,不是想怎么用就怎么用的。
关于数据结构的实现方式也是千差万别,例如队列的实现可以使用数组实现也可以使用链表实现,这里,我们使用的是链表的方式。
一,队列的概念
队列:
只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的特性
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
二,队列结构的实现
队列的结构成员有头指针front(指向单链表的头结点的指针),尾指针rear(指向单链表的尾结点的指针)和表示单链表长度的size
(至于为何如此设计,我们暂时不深究,先学习如何实现队列,而其中的意味我需要慢慢探究)
typedef int QueueDataType;
typedef struct QueueListNode
{
QueueDataType data;
struct QueueListNode* next;
}QNode;
typedef struct Queue
{
QNode* front;
QNode* rear;
int size;
}Queue;
三,队列与单链表的比较
队列和单链表可以说是两回事,但是队列是依靠单链表实现的,通过头节点、尾节点控制单链表实现功能,但它绝不是单链表。
四,队列接口的实现
1,基本接口
初始化:void QueueInit(Queue* pQ);
使用者在创建一个队列的变量之后,将其指针传入初始化函数中,初始化函数将其成员全部置空
void QueueInit(Queue* pQ)
{
assert(pQ != NULL);
pQ->front = NULL;
pQ->rear = NULL;
pQ->size = 0;
}
销毁:void QueueDestroy(Queue* pQ);
遍历单链表,释放动态开辟的空间,将队列成员全部置空
void QueueDestroy(Queue* pQ)
{
assert(pQ != NULL);
QNode* cur = pQ->front;
while (cur != NULL)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pQ->front = pQ->rear = NULL;
pQ->size = 0;
}
2,处理数据接口
插入数据:void QueuePush(Queue* pQ, QueueDataType x);
队列数据的插入就是单链表数据的插入
QNode* BuyNewNode(QueueDataType x)
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
newnode->data = x;
newnode->next = NULL;
return newnode;
}
void QueuePush(Queue* pQ, QueueDataType x)
{
assert(pQ != NULL);
QNode* newnode = BuyNewNode(x);
if (pQ->front == NULL)
{
pQ->front = pQ->rear = newnode;
}
else
{
pQ->rear->next = newnode;
pQ->rear = newnode;
}
pQ->size++;
}
删除数据:void QueuePop(Queue* pQ);
队列数据的删除就是单链表数据的删除,注意:当单链表只有一个节点时,将front置空后,需要将rear置空,不然rear就会成为野指针(当单链表只有一个节点时,头指针和尾指针指向同一个节点,该节点被释放后,两个指针都需置空)
void QueuePop(Queue* pQ)
{
assert(pQ != NULL);
assert(pQ->front != NULL);
QNode* next = pQ->front->next;
free(pQ->front);
pQ->front = next;
if (pQ->front == NULL)
{
pQ->rear = NULL;
}
pQ->size--;
}
3,其他接口
判断队列是否为空:bool QueueEmpty(Queue* pQ);
通过节点数量size判断
bool QueueEmpty(Queue* pQ)
{
assert(pQ != NULL);
return pQ->size == 0 ? true : false;
}
队列内元素数量:int QueueSize(Queue* pQ);
通过节点数量size判断
int QueueSize(Queue* pQ)
{
assert(pQ != NULL);
return pQ->size;
}
队头元素:QueueDataType QueueFront(Queue* pQ);
头节点元素即为队头元素
QueueDataType QueueFront(Queue* pQ)
{
assert(pQ != NULL);
assert(QueueEmpty(pQ) != true);
return pQ->front->data;
}
队尾元素:QueueDataType QueueBack(Queue* pQ);
尾节点元素即为队尾元素
QueueDataType QueueBack(Queue* pQ)
{
assert(pQ != NULL);
assert(QueueEmpty(pQ) != true);
return pQ->rear->data;
}