文章目录
队列
1.1 队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 , 出队列:进行删除操作的一端称为队头
1.2 队列的实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
1.3 队列的代码实现
文件名 | 功能 |
---|---|
Queue.h | 创建队列,完成函数名的声明 |
Queue.c | 实现队列的各个功能函数 |
test.c | 测试队列函数的正确性 |
1.3.1 队列存储的说明
head指针:指向队头元素
tail指针:指向队尾元素
空队时:tail = NULL && head =NULL
队列初始化:tail = head = 0
入队:队未满时,先送值到队尾,再队尾指针加一, 类似于链表的尾插
出队:队为空时,先取队头元素,再队头指针加一, 类似于链表的头删
1.3.2 队列的定义
typedef int QDataType;
typedef struct QueueNode //定义队列结点
{
QDataType data;
struct QueueNode* next;
}QNode;
typedef struct Queue //定义队列结构
{
QNode* head; //队列头指针
QNode* tail; //队列尾指针
int sz; //计算队列的元素个数
}Queue;
1.3.3 初始化队列
void QueueInit(Queue* pq)
{
assert(pq);
pq->head =pq->tail= NULL;
pq->sz = 0;
}
1.3.4 队列的入队
思路:
类似于单链表的尾插操作, 每次入队前开辟一块空间, 对数据进行尾插, 分清第一次入队和非第一次入队, 同时队列的元素个数增加。
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
if (pq->head == NULL) //第一次入队
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
newnode->data = x;
newnode->next = NULL;
pq->sz++;
}
1.3.5 队列的出队
思路:
队列中只有一个元素时直接释放此结点(就是队头结点), 否则保存要删除的值指向下一个结点。
队列为空不能出队
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
if (pq->head->next == NULL) //队列中只剩一个元素 ---> 直接释放
{
free(pq->head);
pq->head = pq->tail=NULL;
}
else
{
QNode* del = pq->head; //保存要删除的值, 指向下一个,
pq->head = pq->head->next;
free(del);
}
pq->sz--;
}
1.3.6 获取队头元素
思路:
直接返回队头指针指向的元素。
队列为空不能获取队头元素
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
1.3.7 获取队尾元素
思路:
直接返回队尾指针指向的元素。
队列为空不能获取队尾元素
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
1.3.8 队列的判空操作
思路:
判断头指针和尾指针是否为空。
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL && pq->tail == NULL;
}
1.3.9 计算队列的元素个数
思路:
直接返回队列的元素个数
可以不定义sz这个变量直接遍历来得到队列的元素个数, 这样的时间复杂度就是O(n),定义一个变量直接返回队列的元素个数时以空间换时间, 时间复杂度是O(1)。
int QueueSize(Queue* pq)
{
assert(pq);
return pq->sz;
}
1.3.10 销毁队列
思路:
遍历一遍队列直接将结点free。
注意将队头指针和队尾指针置空
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* del = cur; //保存要删除的值, 指向下一个, free掉要删除的值
cur = cur->next;
free(del);
}
pq->head = pq->tail = NULL;
pq->sz = 0;
}