1.队列的相关知识
- 队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列先入先出
出队 入队
队头 队尾
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
- 数组队列
- 链式队列2
2.队列的实现
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}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);//判断是否为空
#include "queue.h"
//初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
}
//释放
void QueueDestroy(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->head;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = NULL;
pq->tail = NULL;
}
//队尾插入
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
//队头删除
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QueueNode* next = pq->head->next;
free(pq->head);
pq->head = next;
if (pq->head == NULL)
{
pq->tail = NULL;
}
}
//取队头的数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
//取队尾的数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
//计算含有多少个数据
int QueueSize(Queue* pq)
{
int n = 0;
QueueNode* cur = pq->head;
while (cur)
{
++n;
cur = cur->next;
}
}
//判断是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL;
}
#include "queue.h"
void TestQueue1()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
}
void TestQueue2()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
while (!QueueEmpty(&q))
{
QDataType front = QueueFront(&q);
printf("%d ", front);
QueuePop(&q);
}
printf("\n");
}
int main()
{
//TestQueue1();
TestQueue2();
return 0;
}
3.用队列实现栈
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
//使用两个队列实现一个栈,并支持push,pop,top,empty四种操作
typedef int QDataType;
//实现队列
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}Queue;
//初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
}
//释放
void QueueDestroy(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->head;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = NULL;
pq->tail = NULL;
}
//队尾插入
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
//判断是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL;
}
//队头删除
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QueueNode* next = pq->head->next;
free(pq->head);
pq->head = next;
if (pq->head == NULL)
{
pq->tail = NULL;
}
}
//取队头的数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
//取队尾的数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
//计算含有多少个数据
int QueueSize(Queue* pq)
{
int n = 0;
QueueNode* cur = pq->head;
while (cur)
{
++n;
cur = cur->next;
}
}
typedef struct
{
Queue q1;
Queue q2;
}MyStack;
MyStack* myStackCreate()
{
MyStack* st=(MyStack*)malloc(sizeof(MyStack));
QueueInit(&st->q1);
QueueInit(&st->q2);
return st;
}
void myStackPush(MyStack* obj,int x)
{
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
//[1 2 3 4]
//[ ]
//[ 4] pop
//[1 2 3 ]
int myStackPop(MyStack* obj)
{
Queue* emptyQ=&obj->q1;
Queue* nonemptyQ=&obj->q2;
if(!QueueEmpty(&obj->q1))
{
emptyQ=&obj->q2;
nonemptyQ=&obj->q2;
}
while(QueueSize(nonemptyQ)>1)
{
QueuePush(emptyQ,QueueFront(nonemptyQ));
QueuePop(nonemptyQ);
}
int top=QueueFront(nonemptyQ);
QueuePop(nonemptyQ);
return top;
}
int myStackTop(MyStack* obj)
{
if(!QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q1);
}
else
{
return QueueBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj)
{
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj)
{
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}
int main()
{
MyStack* st=myStackCreate();
myStackPush(st,1);
myStackPush(st,2);
myStackPush(st,3);
myStackPop(st);
myStackFree(st);
return 0;
}
4.用栈实现队列
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
//用两个栈实现队列,支持 push,pop,peek,empty
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top; //栈顶的位置
int capacity;
}ST;
//初始化
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0; //ps->top=-1; 初始化时,top给0,意味着top指向栈顶数据的下一个
//初始化时,top给-1,意味着top指向栈顶数据
ps->capacity = 0;
}
//释放
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
//插入
void StackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
//判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
//删除
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
//取栈顶的数据
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
//求栈中数据个数
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
typedef struct
{
ST pushST;
ST popST;
}MyQueue;
MyQueue* myQueueCreate()
{
MyQueue* q=(MyQueue*)malloc(sizeof(MyQueue));
StackInit(&q->pushST);
StackInit(&q->popST);
return q;
}
void myQueuePush(MyQueue* obj,int x)
{
StackPush(&obj->pushST,x);
}
int myQueuePop(MyQueue* obj)
{
//如果popST中没有数据,就将pushST的数据导过去
//popST 中的数据就符合先进先出的顺序
if(StackEmpty(&obj->popST))
{
while(!StackEmpty(&obj->pushST))
{
StackPush(&obj->popST,StackTop(&obj->pushST));
StackPop(&obj->pushST);
}
}
int front=StackTop(&obj->popST);
StackPop(&obj->popST);
return front;
}
int myStackPeek(MyQueue* obj)
{
//如果popST中没有数据,就将pushST的数据导过去
//popST 中的数据就符合先进先出的顺序
if(StackEmpty(&obj->popST))
{
while(!StackEmpty(&obj->pushST))
{
StackPush(&obj->popST,StackTop(&obj->pushST));
StackPop(&obj->pushST);
}
}
return StackTop(&obj->popST);
}
bool myQueueEmpty(MyQueue* obj)
{
return StackEmpty(&obj->pushST)&&StackEmpty(&obj->popST);
}
void myQueueFree(MyQueue* obj)
{
StackDestroy(&obj->pushST);
StackDestroy(&obj->popST);
free(obj);
}
int main()
{
return 0;
}
5.循环队列的实现
//符合先进先出
//队尾被链接在队首之后
//空间大小固定,可重复利用
//重点:循环队列,无论使用数组实现还是链表实现,都要多开一个空间
// 意味着,要是存K个数据的循环队列,要开K+1个空间
// 否则无法判空和判满(front=tail时可能空也可能满)
//空:front==tail
//满:数组: (tail+1)%(k+1)==front 链表:tail->next=front
//数组实现
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct
{
int* a;
int front;
int tail;
int k;//环形队列的大小
}MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k)
{
MyCircularQueue* cq=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
cq->a=(int*)malloc(sizeof(int)*k+1);
cq->front=0;
cq->tail=0;
cq->k=k;
return cq;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->front==obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
return (obj->tail+1)%(obj->k+1)==obj->front;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj,int value)//插入数据,成功为真
{
if(myCircularQueueIsFull(obj))
{
return false;
}
obj->a[obj->tail]=value;
++obj->tail;
obj->tail%=(obj->k+1);
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)//删除数据,成功为真
{
if(myCircularQueueIsEmpty(obj))
{
return false;
}
++obj->front;
obj->front%=(obj->k+1);
return true;
}
int myCircularQueueFront(MyCircularQueue* obj)//返回队头的值
{
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->a[obj->front];
}
int myCircularQueueRear(MyCircularQueue* obj)//返回队尾的值
{
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
//方法一
if(obj->tail==0)
{
return obj->a[obj->k];
}
else
{
return obj->a[obj->tail-1];
}
//方法二
//int i=(obj->tail+obj->k)%(obj->k+1);
//return obj->a[i];
}
void myCircularQueueFree(MyCircularQueue* obj)
{
free(obj->a);
free(obj);
}
int main()
{
return 0;
}