一:队列的概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表;
队列具有先进先出 FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头、
二:队列的实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数 组头上出数据,效率会比较低。
图解:
代码:
queue.h
#ifndef _QUEUE_H_
#define _QUEUE_H_
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int QDataType;
typedef struct QNode
{
struct QNode* _pNext;
QDataType _data;
}QNode;
typedef struct Queue
{
QNode * _front;//队头
QNode * _back;//队尾
}Queue;
void QueueInit(Queue *q);// 初始化
void QueuePush(Queue *q, QDataType x);//入队列
void QueuePop(Queue *q);//出队列
QDataType QueueFrount(Queue *q);//获取头
QDataType QueueBack(Queue *q);//获取尾
int QueueSize(Queue *q);//队列大小
int QueueEmpty(Queue *q);//判空
void QueueDestroy(Queue *q);//销毁
void QueueShow(Queue *q);//打印
#endif // !_QUEUE_H_
queue.c
#include"queue.h"
void QueueInit(Queue *q)// 初始化
{
assert(q);
q->_back = NULL;
q->_front = NULL;
}
QNode *BuyQueueNode(QDataType x)//创建一个新节点
{
QNode* pNewNode = (QNode*)malloc(sizeof(QNode));
if (NULL == pNewNode)
{
assert(0);
return;
}
pNewNode->_data = x;
pNewNode->_pNext = NULL;
return pNewNode;
}
void QueuePush(Queue *q, QDataType x)//入队列
{
assert(q);
QNode *pNewNode = BuyQueueNode(x);
if (QueueEmpty(q))
{
q->_back = pNewNode;
q->_front = pNewNode;
}
else
{
q->_back->_pNext = pNewNode;
q->_back = pNewNode;
}
}
void QueuePop(Queue *q)//出队列
{
assert(q);
if (q->_front == NULL)
{
return;
}
QNode *pDelete = q->_front;
if(NULL == q->_front)
{
q->_back = NULL;
q->_front = NULL;
}
else
{
q->_front = q->_front->_pNext;
}
free(pDelete);
}
QDataType QueueFrount(Queue *q)//获取头
{
assert(q);
return q->_front->_data;
}
QDataType QueueBack(Queue *q)//获取尾
{
assert(q);
return q->_back->_data;
}
int QueueSize(Queue *q)//队列大小
{
assert(q);
int count = 0;
QNode *pCur = q->_front;
while (pCur)
{
pCur = pCur->_pNext;
count++;
}
return count;
}
int QueueEmpty(Queue *q)//判空
{
assert(q);
return NULL == q->_front;
}
void QueueDestroy(Queue *q)//销毁
{
assert(q);
QNode *pCur = q->_front;
while (pCur)
{
q->_front = pCur->_pNext;
free(pCur);
pCur = q->_front;
}
q->_back = NULL;
q->_front = NULL;
}
void QueueShow(Queue *q)//打印
{
assert(q);
QNode *qCur = q->_front;
printf("元素是");
while (qCur)
{
printf("%-3d", qCur->_data);
qCur = qCur->_pNext;
}
printf("\n");
}
test.c
#include"queue.h"
void test()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueueShow(&q);
QueuePop(&q);
QueueShow(&q);
int k = QueueBack(&q);
printf("最后一个元素是%d\n", k);
k = QueueFrount(&q);
printf("第一个元素是%d\n", k);
QueuePush(&q, 4);
QueuePush(&q, 5);
QueueShow(&q);
k = QueueSize(&q);
printf("队列大小=%d\n", k);
}
int main()
{
test();
system("pause");
return 0;
}
输出结果:
三:用对列实现栈
题目描述:
使用队列实现栈的下列操作:
push(x) -- 元素 x 入栈
pop() -- 移除栈顶元素
top() -- 获取栈顶元素
empty() -- 返回栈是否为空
解析:
首先我们看一下堆和栈的特点:
队列:先进后出
栈:先进先出
然后我们在逐个进行分析:
1:push(x) -- 元素 x 入栈
根据栈和队列的特点其入栈和入队列是相同的,故在这点上我们无需做出特殊处理;
2:pop() -- 移除栈顶元素
由于队列是先进先出的而栈是先进后出,所以我们需要在这里做出一些特殊的处理;
我们给出的方法是设计两个队列p1和p2在每次移除时先将队列前的所有元素移动到另一个队列中,这样剩余的最后一个元素就是栈顶(也是队尾)了;
如图:
3:top() -- 获取栈顶元素
只需将队列队尾返回即可
4:empty() -- 返回栈是否为空
判空即可
代码:LeetCode版本
typedef int QDataType;
typedef struct QNode
{
struct QNode* _pNext;
QDataType _data;
}QNode;
typedef struct Queue
{
QNode * _front;//队头
QNode * _back;//队尾
}Queue;
void QueueInit(Queue *q)// 初始化
{
assert(q);
q->_back = NULL;
q->_front = NULL;
}
int QueueEmpty(Queue *q)//判空
{
assert(q);
return NULL == q->_front;
}
QNode *BuyQueueNode(QDataType x)//创建一个新节点
{
QNode* pNewNode = (QNode*)malloc(sizeof(QNode));
if (NULL == pNewNode)
{
assert(0);
}
pNewNode->_data = x;
pNewNode->_pNext = NULL;
return pNewNode;
}
void QueuePush(Queue *q, QDataType x)//入队列
{
assert(q);
QNode *pNewNode = BuyQueueNode(x);
if (QueueEmpty(q))
{
q->_back = pNewNode;
q->_front = pNewNode;
}
else
{
q->_back->_pNext = pNewNode;
q->_back = pNewNode;
}
}
void QueuePop(Queue *q)//出队列
{
assert(q);
if (q->_front == NULL)
{
return;
}
QNode *pDelete = q->_front;
if(NULL == q->_front)
{
q->_back = NULL;
q->_front = NULL;
}
else
{
q->_front = q->_front->_pNext;
}
free(pDelete);
}
QDataType QueueFrount(Queue *q)//获取头
{
assert(q);
return q->_front->_data;
}
QDataType QueueBack(Queue *q)//获取尾
{
assert(q);
return q->_back->_data;
}
int QueueSize(Queue *q)//队列大小
{
assert(q);
int count = 0;
QNode *pCur = q->_front;
while (pCur)
{
pCur = pCur->_pNext;
count++;
}
return count;
}
void QueueDestroy(Queue *q)//销毁
{
assert(q);
QNode *pCur = q->_front;
while (pCur)
{
q->_front = pCur->_pNext;
free(pCur);
pCur = q->_front;
}
q->_back = NULL;
q->_front = NULL;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
/** Initialize your data structure here. */
MyStack* myStackCreate() {
MyStack *pms = (MyStack*)malloc(sizeof(MyStack));
if(NULL == pms)
{
assert(0);
return 0;
}
QueueInit(&pms->q1);
QueueInit(&pms->q2);
return pms;
}
/** Push element x onto stack. */
void myStackPush(MyStack* obj, int x) {
assert(obj);
if(QueueEmpty(&obj->q1))
QueuePush(&obj->q2,x);
else
QueuePush(&obj->q1,x);
}
/** Removes the element on top of the stack and returns that element. */
int myStackPop(MyStack* obj) {
assert(obj);
if(!QueueEmpty(&obj->q1))
{
//将q1中的前n-1个元素移到q2中
int count = QueueSize(&obj->q1);
while(count > 1)
{
QueuePush(&obj->q2,QueueFrount(&obj->q1));
QueuePop(&obj->q1);
count--;
}
int ret= QueueBack(&obj->q1);
QueuePop(&obj->q1);
return ret;
}
else
{
//将q2中的前n-1个元素移到q1中
int count = QueueSize(&obj->q2);
while(count > 1)
{
QueuePush(&obj->q1,QueueFrount(&obj->q2));
QueuePop(&obj->q2);
count--;
}
int ret= QueueBack(&obj->q2);
QueuePop(&obj->q2);
return ret;
}
}
/** Get the top element. */
int myStackTop(MyStack* obj) {
assert(obj);
if(QueueEmpty(&obj->q1))
return QueueBack(&obj->q2);
else
return QueueBack(&obj->q1);
}
/** Returns whether the stack is empty. */
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}