数据结构(初阶)笔记归纳8:栈和队列

栈和队列

目录

栈和队列

一、栈的概念及结构

1.1.栈的概念

1.2.栈的特性

1.3.栈的三种实现结构

二、动态顺序表实现栈

2.1.栈的文件结构

2.2.头文件编写

2.2.1.头文件包含

2.2.2.数组元素重命名

2.2.3.栈结构的定义

2.2.4.栈的初始化

2.2.5.栈的销毁

2.2.6.压栈

2.2.7.出栈

2.2.8.获取栈顶数据

2.2.9.判断栈是否为空

2.2.10.计算当前数据个数

2.3.源文件编写

2.3.1.头文件包含

2.3.2.栈的初始化

2.3.3.栈的销毁

2.3.4.压栈

2.3.5.出栈

2.3.6.获取栈顶数据

2.3.7.判断栈是否为空

2.3.8.计算当前数据个数

2.4.测试文件编写

2.4.1.测试文件01

三、与栈有关的试题

试题1:有效的括号

四、队列的概念及结构

4.1.队列的概念

4.2.队列的特性

4.3.经典应用

4.3.1.生产者消费者模型

4.3.2.广度优先遍历(BFS)

五、单链表实现队列

5.1.栈的文件结构

5.2.头文件编写

5.2.1.头文件包含

5.2.2.节点数据类型重命名

5.2.3.节点结构定义

5.2.4.头尾结构定义

5.2.5.队列的初始化

5.2.6.队尾插入

5.2.7.队头删除

5.2.8.计算当前数据个数

5.2.9.取队头数据

5.2.10.取队尾数据

5.2.11.判断队列是否为空

5.2.12.队列的销毁

5.3.源文件编写

5.3.1.头文件包含

5.3.2.队列的初始化

5.3.3.队尾插入

5.3.4.队头删除

5.3.5.计算当前数据个数

5.3.9.取队头数据

5.3.10.取队尾数据

5.3.11.判断队列是否为空

5.3.12.队列的销毁

5.4.测试文件编写

5.4.1.测试文件01

七、与栈和队列有关的试题

试题2:用队列实现栈

试题3:设计循环队列

试题4:用栈实现队列


一、栈的概念及结构

1.1.栈的概念

一种特殊的线性表

1.2.栈的特性

只允许固定的一端进行插入与删除元素的操作

**栈顶:**进行数据插入与删除的一端

**栈底:**栈顶的另一端

栈中的数据遵循后进先出LIFO(Last In First Out)的原则

**压栈:**栈的插入操作,在栈顶

**出栈:**栈的删除操作,在栈顶

类似于向羽毛球桶取放羽毛球

1.3.栈的三种实现结构

**顺序表:**最后一个元素设为栈顶

**双向链表:**最后一个节点设为栈顶

**单链表:**第一个节点设为栈顶

二、动态顺序表实现栈

2.1.栈的文件结构

  • 头文件(Stack.h):栈的结构创建,栈的方法声明
  • 源文件(Stack.c):栈的方法实现
  • 测试文件(test.c):测试数据结构的方法

2.2.头文件编写

2.2.1.头文件包含
cpp 复制代码
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
2.2.2.数组元素重命名
cpp 复制代码
typedef int STDataType;
2.2.3.栈结构的定义
cpp 复制代码
typedef struct Stack
{
	STDataType* a;//顺序表指针
	int top;//栈顶元素下标
	int capacity;//空间大小
}ST;
2.2.4.栈的初始化
cpp 复制代码
void STInit(ST* pst);
2.2.5.栈的销毁
cpp 复制代码
void STDestroy(ST* pst);
2.2.6.压栈
cpp 复制代码
void STPush(ST* pst, STDataType x);
2.2.7.出栈
cpp 复制代码
void STPop(ST* pst);
2.2.8.获取栈顶数据
cpp 复制代码
STDataType STTop();
2.2.9.判断栈是否为空
cpp 复制代码
bool STEmpty(ST* pst);
2.2.10.计算当前数据个数
cpp 复制代码
int STSize(ST* pst);

2.3.源文件编写

2.3.1.头文件包含
cpp 复制代码
#include "Stack.h"
2.3.2.栈的初始化
cpp 复制代码
void STInit(ST* pst)
{
	assert(pst);

	pst->a = NULL;
    pst->top = pst->capacity = 0;
}

注:

如果top初值为0,则top永远指向栈顶数据的下一个位置(该值与当前栈中数据个数相同)

如果top初值为-1,则top永远指向栈顶数据的位置

2.3.3.栈的销毁
cpp 复制代码
void STDestroy(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}
2.3.4.压栈
cpp 复制代码
void STPush(ST* pst, STDataType x)
{
	assert(pst);

	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			return;
		}

		pst->a = tmp;
		pst->capacity = newcapacity;
	}

	pst->a[pst->top] = x;
	pst->top++;
}
2.3.5.出栈
cpp 复制代码
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	pst->top--;
}
2.3.6.获取栈顶数据
cpp 复制代码
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	return pst->a[pst->top - 1];
}
2.3.7.判断栈是否为空
cpp 复制代码
bool STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == 0;
}
2.3.8.计算当前数据个数
cpp 复制代码
int STSize(ST* pst)
{
	assert(pst);

	return pst->top;
}

2.4.测试文件编写

2.4.1.测试文件01
cpp 复制代码
void Test01()
{
    /*创建栈的结构*/
	ST s;

    /*栈的初始化*/
	STInit(&s);

    /*压栈*/
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);

    /*出栈*/
	STPop(&s);
	STPop(&s);

    /*栈顶元素*/
	printf("%d\n", STTop(&s));

    /*栈的打印*/
    while(!STEmpty(&s))
    {
        printf("%d\n",STTop(&s));
        STPop(&s);//只有把当前栈顶元素拿到才能访问下一个
    }

    /*栈的销毁*/
	STDestroy(&s);
}

int main()
{
	Test01();
	return 0;
}

三、与栈有关的试题

试题1:有效的括号

题目内容:

给定一个只包括 '('')''{''}''['']' 的字符串s,判断字符串是否有效

有效字符串需满足:

左括号必须用相同类型的右括号闭合

左括号必须以正确的顺序闭合

每个右括号都有一个对应的相同类型的左括号

示例1:

输入:s = "()"

输出:true

示例2:

输入:s = "([)]"

输出:false

思路解析:

如果是左括号就入栈,遇到右括号时,将栈顶元素与右括号匹配

如果匹配成功,判断栈中是否有多余左括号,返回判断的布尔值

如果匹配失败,就直接销毁栈

代码部分:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef char STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void STInit(ST* pst)
{
	assert(pst);

	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

void STDestroy(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

void STPush(ST* pst, STDataType x)
{
	assert(pst);

	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			return;
		}

		pst->a = tmp;
		pst->capacity = newcapacity;
	}

	pst->a[pst->top] = x;
	pst->top++;
}

void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	pst->top--;
}

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->a[pst->top - 1];
}

bool STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == 0;
}

bool isValid(char* s) {
    ST st;
    STInit(&st);
    while(*s)
    {
        if(*s == '(' || *s == '[' || *s =='{')
        {
            STPush(&st,*s);
        }
        else
        {
            if(STEmpty(&st))
            {
                return false;
            }
            char top = STTop(&st);
            STPop(&st);

            if((top == '('&&*s != ')')
            ||(top == '{'&&*s != '}')
            ||(top == '['&&*s != ']'))
            {
                STDestroy(&st);
                return false;
            }
        }
        ++s;
    }

    /*如果栈不为空,说明左括号比右括号多*/
    bool ret = STEmpty(&st);
    STDestroy(&st);

    return ret;
}

四、队列的概念及结构

4.1.队列的概念

一种特殊的线性表

4.2.队列的特性

只允许在一端插入数据,在另一端删除数据

入队列: 进行插入操作的一端为队尾

出队列: 进行删除操作的一端为队头

队列中的数据遵循先进先出(First In First Out)的原则

类似于排队买奶茶,先到先得

4.3.经典应用

4.3.1.生产者消费者模型

生产者:医院挂号机(3,4,5,6,7......)

消费者:医生叫号(先叫3,再叫4)

公平性:队列的先进先出,保证了先到的号先被处理,不会插队

锁:保证一个时间只有一个线程操作队列(叫号叫到3,让3既到3号机又到4号机)

4.3.2.广度优先遍历(BFS)

将好友关系用图来表示:

给小徐推荐好友

以一个点为源点,一圈一圈扩散地寻找好友

边连接着直接好友小王、小明

直接好友的好友是小花、小张

直接好友的好友的好友是小杨

给小徐推荐直接好友的好友:

小徐入队列

小徐出队列,小徐的直接好友入队列

小明出队列,小明的直接好友入队列

小王出队列,小王的直接好友入队列

此时队列中的好友就是小徐直接好友的好友

五、单链表实现队列

5.1.栈的文件结构

  • 头文件(Queue.h):队列的结构创建,队列的方法声明
  • 源文件(Queue.c):队列的方法实现
  • 测试文件(test.c):测试数据结构的方法

5.2.头文件编写

5.2.1.头文件包含
cpp 复制代码
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
5.2.2.节点数据类型重命名
cpp 复制代码
typedef int QDataType;
5.2.3.节点结构定义
cpp 复制代码
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType val;
}QNode;
5.2.4.头尾结构定义
cpp 复制代码
typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
    int size;
}Queue;

注:

将头指针,尾指针,以及节点个数封装成一个结构体

只需传送这个结构体的地址,就能完成对指针变量的修改

减少了传送的参数个数,避免了传送二级指针

**问:**同样是单链表,为什么实现队列时可以创建头尾结构?

因为这种头尾结构可以轻松实现尾插,但实现尾删非常麻烦

因为不方便寻找倒数第二个节点

5.2.5.队列的初始化
cpp 复制代码
void QueueInit(Queue* pq);
5.2.6.队尾插入
cpp 复制代码
void QueuePush(Queue* pq, QDataType x);
5.2.7.队头删除
cpp 复制代码
void QueuePop(Queue* pq);
5.2.8.计算当前数据个数
cpp 复制代码
int QueueSize(Queue* pq);
5.2.9.取队头数据
cpp 复制代码
QDataType QueueFront(Queue* pq);
5.2.10.取队尾数据
cpp 复制代码
QDataType QueueBack(Queue* pq);
5.2.11.判断队列是否为空
cpp 复制代码
bool QueueEmpty(Queue* pq);
5.2.12.队列的销毁
cpp 复制代码
void QueueDestroy(Queue* pq);

5.3.源文件编写

5.3.1.头文件包含
cpp 复制代码
#inlcude "Queue.h"
5.3.2.队列的初始化
cpp 复制代码
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
5.3.3.队尾插入
cpp 复制代码
void QueuePush(Queue* pq, QDataType x)
{
	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++;
}
5.3.4.队头删除
cpp 复制代码
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

    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--;
}
5.3.5.计算当前数据个数
cpp 复制代码
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}
5.3.9.取队头数据
cpp 复制代码
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);

	return pq->phead->val;
}
5.3.10.取队尾数据
cpp 复制代码
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);

	return pq->ptail->val;
}
5.3.11.判断队列是否为空
cpp 复制代码
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}
5.3.12.队列的销毁
cpp 复制代码
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;
}

5.4.测试文件编写

5.4.1.测试文件01
cpp 复制代码
void Test01()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);

    while(!QueueEmpty(&q))
    {
        printf("%d ",QueueFront(&q));
        QueuePop(&q);
    }
    printf("\n");
}

int main()
{
	Test01();
	return 0
}

七、与栈和队列有关的试题

试题2:用队列实现栈

题目内容:

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作

(push、top、pop、和empty)

示例:

输入:

"MyStack","push","push","top","pop","empty"

\[\],\[1\],\[2\],\[\],\[\],\[\]

输出:

NULL,NULL,NULL,2,2,false

思路解析:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.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)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDataType x)
{
	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);

	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--;
}

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}

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;
}

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;
}

int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

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) {
    if(!QueueEmpty(&(obj->q1)))
    {
        QueuePush(&(obj->q1),x);
    }
    else
    {
        QueuePush(&(obj->q2),x);
    }
}

int myStackPop(MyStack* obj) {
    //假设法
    Queue* empty = &(obj->q1);
    Queue* nonEmpty = &(obj->q2);
    if(!QueueEmpty(&(obj->q1)))
    {
        nonEmpty = &(obj->q1);
        empty = &(obj->q2);
    }

    while(QueueSize(nonEmpty) > 1)
    {
        QueuePush(empty,QueueFront(nonEmpty));
        QueuePop(nonEmpty);
    }

    int top = QueueFront(nonEmpty);
    QueuePop(nonEmpty);

    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);
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

试题3:设计循环队列

题目内容:

设计你的循环队列

循环队列:

一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环,它也被称为环形缓冲器

循环队列好处:

在一个普通队列里,一旦一个队列满了,就不能插入下一个元素,即使在队列前面仍有空间,但是使用循环队列,可以利用这个队列之前用过的空间,使用这些空间去存储新的值

你的实现应该支持如下操作:

MyCircularQueue(k):构造器 设置队列长度为 k

Front:从队首获取元素 如果队列为空,返回 -1

Rear:获取队尾元素 如果队列为空,返回 -1

enQueue(value):向循环队列插入一个元素 如果成功插入则返回真

deQueue():从循环队列中删除一个元素 如果成功删除则返回真

isEmpty():检查循环队列是否为空

isFull():检查循环队列是否已满

示例:

MyCircularQueue circularQueue = new

MyCircularQueue(3);//设置长度为 3

circularQueue.enQueue(1);//返回 true

circularQueue.enQueue(2);//返回 true

circularQueue.enQueue(3);//返回 true

circularQueue.enQueue(4);//返回 false

队列已满

circularQueue.Rear();//返回 3

circularQueue.isFull();//返回 true

circularQueue.deQueue();//返回 true

circularQueue.enQueue(4);//返回 true

circularQueue.Rear();//返回4

代码部分:

cpp 复制代码
typedef struct 
{
    int* a;
    int head;
    int tail;
    int k;
} MyCircularQueue;

MyCircularQueue* myCircularQueueCreate(int k) 
{
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));

    obj->a = (int*)malloc(sizeof(int)*(k+1));
    obj->head = 0;
    obj->tail = 0;
    obj->k = k;

    return obj;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
    return obj->head == obj->tail;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) 
{
    return (obj->tail+1)%(obj->k+1) == obj->head;
}

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->head;

    obj->head %= obj->k+1;
    
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        return obj->a[obj->head];
    }
}

int myCircularQueueRear(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        return obj->a[(obj->tail + obj->k)%(obj->k + 1)];
    }
}

void myCircularQueueFree(MyCircularQueue* obj) 
{
    free(obj->a);
    free(obj);
}

/**
 * Your MyCircularQueue struct will be instantiated and called as such:
 * MyCircularQueue* obj = myCircularQueueCreate(k);
 * bool param_1 = myCircularQueueEnQueue(obj, value);
 
 * bool param_2 = myCircularQueueDeQueue(obj);
 
 * int param_3 = myCircularQueueFront(obj);
 
 * int param_4 = myCircularQueueRear(obj);
 
 * bool param_5 = myCircularQueueIsEmpty(obj);
 
 * bool param_6 = myCircularQueueIsFull(obj);
 
 * myCircularQueueFree(obj);
*/

试题4:用栈实现队列

题目内容:

请你仅使用两个栈实现先入先出队列

队列应当支持一般队列支持的所有操作(push,pop,peek,empty)

示例:

输入:["MyQueue","push","push","peek","pop","empty"]

\[\],\[1\],\[2\],\[\],\[\],\[\]

输出:[NULL,NULL,NULL,1,1,false]

代码部分:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef char STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void STInit(ST* pst)
{
	assert(pst);

	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

void STDestroy(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

void STPush(ST* pst, STDataType x)
{
	assert(pst);

	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			return;
		}

		pst->a = tmp;
		pst->capacity = newcapacity;
	}

	pst->a[pst->top] = x;
	pst->top++;
}

void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	pst->top--;
}

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->a[pst->top - 1];
}

bool STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == 0;
}

typedef struct 
{
    ST pushst;
    ST popst;
} MyQueue;


MyQueue* myQueueCreate() 
{
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));

    STInit(&(obj->pushst));
    STInit(&(obj->popst));

    return obj;
}

void myQueuePush(MyQueue* obj, int x) 
{
    STPush(&(obj->pushst),x);
}

int myQueuePeek(MyQueue* obj) 
{
    if(STEmpty(&(obj->popst)))
    {
        while(!STEmpty(&(obj->pushst)))
        {
            int top = STTop(&(obj->pushst));
            STPush(&(obj->popst),top);
            STPop(&(obj->pushst));
        }
    }
    return STTop(&(obj->popst));
}

int myQueuePop(MyQueue* obj) 
{
    int front = myQueuePeek(obj);
    STPop(&(obj->popst));
    return front;
}

bool myQueueEmpty(MyQueue* obj) 
{
    return STEmpty(&(obj->popst)) && STEmpty(&(obj->pushst));
}

void myQueueFree(MyQueue* obj) 
{
    STDestroy(&(obj->popst));
    STDestroy(&(obj->pushst));

    free(obj);
}

/**
 * Your MyQueue struct will be instantiated and called as such:
 * MyQueue* obj = myQueueCreate();
 * myQueuePush(obj, x);
 
 * int param_2 = myQueuePop(obj);
 
 * int param_3 = myQueuePeek(obj);
 
 * bool param_4 = myQueueEmpty(obj);
 
 * myQueueFree(obj);
*/
相关推荐
朗迹 - 张伟2 小时前
UE5 City Traffic Pro 交通插件学习笔记
笔记·学习·ue5
one____dream2 小时前
【算法】移除链表元素与反转链表
数据结构·python·算法·链表
睡不醒的kun2 小时前
不定长滑动窗口-基础篇(2)
数据结构·c++·算法·leetcode·哈希算法·散列表·滑动窗口
gihigo19982 小时前
MATLAB实现K-SVD算法
数据结构·算法·matlab
SJLoveIT2 小时前
架构师视角:深度解构 Redis 底层数据结构的设计哲学
数据结构·数据库·redis
running up that hill2 小时前
日常刷题记录
java·数据结构·算法
@––––––2 小时前
论文学习笔记:FAST - 高效的视觉-语言-动作模型动作分词技术
笔记·学习
Gain_chance2 小时前
22-学习笔记尚硅谷数仓搭建-日志表建表语句解析、数据装载及脚本装载数据
数据仓库·笔记·学习
傻小胖3 小时前
8.BTC-挖矿-北大肖臻老师客堂笔记
笔记