1. 队列的概念
一种只能从一端进从另一端出的线性表(类似于商场排队)
2.为啥要发明队列
利用队列能更加简洁方便的解决问题
利用队列能解决很多实际问题:例如预约点餐,时间上的公平性,找到共同好友等等
3.队列的具体实现
1.初始化
由于需要有一端计入数据还得有一端寄出数据所以需要定义一个头指针和尾指针
但是在写函数传参的时候需要写两个二重指针,显得接口不太整齐,书写复杂,
于是我们就可以利用一个新的结构体将其装起来一起传输
2.队尾插入
1.如果头指针与尾指针都为空不要忘记给头指针赋值(否则容易造成野指针)
2.记得在尾指针后插入数据后,把尾指针的位置也往后推进一格
3.有效数size记得加一方便后面实现总长
3.队头删除
记得对特殊情况进行讨论
1.当元素都没有的情况下
2.当只有一个元素,头尾指针在一起时
4.取队尾和队尾数据
5.记录对列中的个数(size)
由于前面每次队尾插入size都递增了所以直接返回size即可
6.判断队列是否为空
7.队列的销毁
4.代码
Queue.h
Queue.c
5.相关经典题
2.用队列实现栈。OJ链接
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
#include<stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType val;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
int size;
}Queue;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
// 队尾插入
void QueuePush(Queue* pq, QDataType x);
// 队头删除
void QueuePop(Queue* pq);
// 取队头和队尾的数据
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->phead;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
// 队尾插入
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->next = NULL;
newnode->val = x;
if (pq->ptail == NULL)
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
// 队头删除
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->size != 0);
/*QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
if (pq->phead == NULL)
pq->ptail = NULL;*/
// 一个节点
if (pq->phead->next == NULL)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else // 多个节点
{
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
pq->size--;
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->phead->val;
}
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->ptail);
return pq->ptail->val;
}
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size == 0;
}
//题目思路:队列有着先进先出的性质而栈为后进先出,所以需要两个队列,一个队列保持空,另一个吧数据给空队列,
//直到最后留到最后一个数据,然后将其导出就行
typedef struct {
Queue q1;
Queue q2;//定义两个空变量
} MyStack;
MyStack* myStackCreate() {
//局部变量不能出函数所以为其开辟一个空间
MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&(pst->q1));
QueueInit(&(pst->q2));
return pst;
}
void myStackPush(MyStack* obj, int x) {
//将x放入有元素的组里,确保另一个队列为空
if(!QueueEmpty(&(obj->q1)))
{
QueuePush(&(obj->q1),x);
}
else
{
QueuePush(&(obj->q2),x);
}
}
int myStackPop(MyStack* obj) {
//将前size项移走,留最后一项然后导出
//假设法,直接假定一个为空,如果不为空就交换位置
Queue* empty = &(obj->q1);
Queue* noEmpty = &(obj->q2);
if (!QueueEmpty(&(obj->q1)))
{
noEmpty = &(obj->q1);
empty = &(obj->q2);
}
while(QueueSize(noEmpty) > 1)//size从零开始所以后面要减一
{
QueuePush(empty,QueueFront(noEmpty));
QueuePop(noEmpty);
}
int top = QueueFront(noEmpty);
QueuePop(noEmpty);
return top;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&(obj->q1)))
{
return QueueBack(&(obj->q1));
}
else
{
return QueueBack(&(obj->q2));
}
}
bool myStackEmpty(MyStack* obj) {//因为QueueEmpty判断方式为0则,有一个不为空就为假
return QueueEmpty(&(obj->q1)) && QueueEmpty(&(obj->q2));
}
void myStackFree(MyStack* obj) {
QueueDestroy(&(obj->q1));//不能忘记obj中存储的链表也要释放空间
QueueDestroy(&(obj->q2));
free(obj);
}