[数据结构] 用两个队列实现栈详解

文章目录

一、队列实现栈的特点分析

1、1 具体分析

1、2 整体概括

二、队列模拟实现栈代码的实现

2、1 手撕 队列 代码

queue.h

queue.c

2、2 用队列模拟实现栈代码

三、总结 


🙋‍♂️ 作者:@Ggggggtm 🙋‍♂️

👀 专栏:数据结构与算法、高频面试问题 👀

💥 标题:用队列模拟栈 💥

 ❣️ 寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景 ❣️

  我们上篇文章讲述了用两个栈实现队列 ,用过对上篇文章的学习后,我们再去学用两个队列实现栈就变得相对来说容易了很多。本篇文章会对用两个队列实现栈进行详解,希望会对你有所帮助。 

一、队列实现栈的特点分析

1、1 具体分析

 队列和栈在插入数据时,队列是从队尾进行插入,栈是从栈顶插入。但是他们的删除数据是不同的。我们知道队列的特点是:先新先出 ,删除数据是在对头进行删除,栈的特点是:先进后出,也就是在栈顶进行删除。

  当我们用队列实现栈时,最根本的也是最重要的是需要解决删除的问题。我们用队列实现栈时,在队列中的删除就不是删除对头的元素了,我们需要根据栈的特点进行删除,也就是我们需要删除的是队尾的元素。

   操作时,首先我们先往队列中插入元素。注意,我们插入元素时,应该往不为空的队列中插入元素,如果两个队列都为空,我们可以随意往一个队列中插入元素。为什么要往不为空的队列中插入元素呢?我们先接着往下看。我们是用队列模拟栈,此时我们想要删除的是栈顶的元素,也就是队尾的元素。我们需要把前size-1个元素移动到另一个空的对列中,然后再删除队列中的最后一个元素,也就是队尾元素  这也是我们为什么插入元素时要往不为空的队列中插入的原因。因为我们需要一个空的队列进行来回导元素,从而达到删除队尾元素的目的。这时,插入操作和删除操作我们都是可以用队列去模拟实现出栈的效果了。插入和删除重复上面的操作就可以。

1、2 整体概括

  通过我们上面的分析,用队列模拟实现栈和用栈模拟队列的思路大同小异。我们看用队列模拟栈的整体思路:

  • 插入时往不为空的队列插入。第一次插入时,两个队列都为空,此时随便插入一个队列即可。
  • 删除时,需要把不为空的队列中的元素前size-1个元素导入到空队列中。然后再删除剩下的一个元素。
  • 返回栈顶的元素,也就是返回队尾的元素。

二、队列模拟实现栈代码的实现

  我们这里用c语言实现,所以还要手撕一个队列的代码。当然C++容器中,有队列,可以直接用。大家熟悉思路后,可以用其它语言做一下本题,OJ链接:用队列实现栈 - OJ链接(LeetCode)。

2、1 手撕 队列 代码

queue.h

typedef int QDataType;

typedef struct QNode
{
	struct QNode* next;
	QDataType data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);

void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);

QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);

bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);

queue.c

void QueueInit(Queue* pq)
{
	assert(pq);

	pq->head = pq->tail = NULL;
	pq->size = 0;
}
void QueueDestory(Queue* pq)
{
	assert(pq);

	QNode* cur =pq->head;

	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* tmp = (QNode*)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("malloc failed");
		exit(-1);
	}
	tmp->next = NULL;
	tmp->data = x;

	if (pq->head == pq->tail && pq->head == NULL)
	{
		pq->head = pq->tail = tmp;
	}
	else
	{
		pq->tail->next = tmp;
		pq->tail = tmp;
	}
	pq->size++;
}
void QueuePop(Queue* pq)
{
	assert(pq);

	assert(pq->head != NULL);

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
    
	pq->size--;
}

2、2 用队列模拟实现栈代码

typedef int QDataType;

typedef struct QNode
{
	struct QNode* next;
	QDataType data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);

void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);

QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);

bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);
void QueueInit(Queue* pq)
{
	assert(pq);

	pq->head = pq->tail = NULL;
	pq->size = 0;
}
void QueueDestory(Queue* pq)
{
	assert(pq);

	QNode* cur =pq->head;

	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* tmp = (QNode*)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("malloc failed");
		exit(-1);
	}
	tmp->next = NULL;
	tmp->data = x;

	if (pq->head == pq->tail && pq->head == NULL)
	{
		pq->head = pq->tail = tmp;
	}
	else
	{
		pq->tail->next = tmp;
		pq->tail = tmp;
	}
	pq->size++;
}
void QueuePop(Queue* pq)
{
	assert(pq);

	assert(pq->head != NULL);

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
    
	pq->size--;
}

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

bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

typedef struct 
{
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() 
{
    MyStack* st=(MyStack*)malloc(sizeof(MyStack));
    if(st==NULL)
        return false;
    
    QueueInit(&st->q1);
    QueueInit(&st->q2);

    return st;
}

void myStackPush(MyStack* obj, int x) 
{
    if(QueueSize(&obj->q1)!=0)
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }
}

int myStackPop(MyStack* obj) 
{
    Queue* tmp=&obj->q1;
    Queue* notmp=&obj->q2;

    if(QueueSize(notmp)==0)
    {
        tmp=&obj->q2;
        notmp=&obj->q1;
    }

    while(QueueSize(notmp)>1)
    {
        QueuePush(tmp,QueueFront(notmp));
        QueuePop(notmp);

    }

    QDataType res=QueueFront(notmp);
    QueuePop(notmp);
    return res;
}

int myStackTop(MyStack* obj) 
{
    if(QueueSize(&obj->q1)!=0)
        return QueueBack(&obj->q1);
    else
        return QueueBack(&obj->q2);
}

bool myStackEmpty(MyStack* obj) 
{
    return QueueEmpty(&obj->q1)  &&  QueueEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) 
{
    QueueDestory(&obj->q1);
    QueueDestory(&obj->q2);

    free(obj);
}

三、总结 

  以上就是整个用队列模拟实现栈的整个过程,主要是利用空队列删除队尾的元素。我们应该熟练掌握用队列模拟实现栈和用栈模拟实现队列,两者都是面试中的高频题目。本篇文章的讲解就到这里,希望以上对容对对你有所帮助,感谢阅读ovo~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/3158.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

入职第一天就被迫离职,找工作多月已读不回,面试拿不到offer我该怎么办?

大多数情况下,测试员的个人技能成长速度,远远大于公司规模或业务的成长速度。所以,跳槽成为了这个行业里最常见的一个词汇。 前言 前几天,我们一个粉丝跟我说,正常入职一家外包,什么都准备好了&#xff0…

Portainer堪称最优秀的容器化管理平台

一、Portainer是什么? Portainer是一款开源的容器管理平台,支持多种容器技术,如Docker、Kubernetes和Swarm等。它提供了一个易于使用的Web UI界面,可用于管理和监控容器和集群。Portainer旨在使容器管理更加简单和可视化&#xf…

WinForm | C# 界面弹出消息通知栏 (仿Win10系统通知栏)

ApeForms 弹出消息通知栏功能 文章目录ApeForms 弹出消息通知栏功能前言全局API通知栏起始方向通知排列方向通知栏之间的间隔距离无鼠标悬停时的不透明度消息通知窗体的默认大小示例代码文本消息提示栏文本消息提示栏(带选项)图文消息提示栏图文消息提示…

【Spring-boot源码剥析】| 启动原理之侠客行篇

目录一. 传说篇二. 快速启动原理三. 自动配置原理3.1 准备阶段3.2 配置阶段3.3 运行阶段三. Pefect Ending一. 传说篇 江湖传说,有一个神秘的江湖大侠,他名叫SpringBoot,擅长于开发出快速启动的应用程序。这个侠客的江湖名号传遍了整个江湖&a…

did not find expected key while parsing a block mapping at line 2 column 1的解决方法

问题描述 真的是困扰了好久的一个问题&#xff0c;真的是邪乎了&#xff0c;报的错误实际上是错的 完整报错&#xff1a; Error: YAML Exception reading /path_to_your_blog/_publications/2020-08-21.md: (<unknown>): did not find expected key while parsing a b…

JQuery

概述&#xff1a; JQuery&#xff1a;JavaScript和查询&#xff0c;他是辅助JavaScript开发的js类库。 他的的核心思想就是write less&#xff0c;do moire 实现了很多浏览器兼容问题 JQuery的核心函数 $(参数) 1 参数是函数&#xff1a;$(function(){}) window.onlooad fun…

AI风暴 :文心一言 VS GPT-4

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 文心一言 VS GPT-4 文心一言&#xff1a;知识增强大语言模型百度全新一代知识增强大语言模型&#xff0c;文心大模型家族的新成员&#xff0c;能够与人对话互动&#…

TryHackMe-Zeno(boot2root)

Zeno 你有和伟大的斯多葛派哲学家芝诺一样的耐心吗&#xff1f;试试吧&#xff01; 端口扫描 循例 nmap Web枚举 进到12340端口 目录扫描 /rms是一个业务站点 在admin登录页面尝试弱口令和注入&#xff0c;也都没有成功 SQLI 在点餐这发现了个get参数id&#xff0c;尝试sql…

八大排序算法之归并排序(递归实现+非递归实现)

目录 一.归并排序的基本思想 归并排序算法思想(排升序为例) 二.两个有序子序列(同一个数组中)的归并(排升序) 两个有序序列归并操作代码: 三.归并排序的递归实现 递归归并排序的实现:(后序遍历递归) 递归函数抽象分析: 四.非递归归并排序的实现 1.非递归归并排序算法…

如何从 Vue CLI 迁移到 Vite

如何从 Vue CLI 迁移到 Vite 十一月11 2021如果你在 2021 年之前一直在使用 Vue 进行开发&#xff0c;那么你选择的构建工具很有可能是 Vue CLI。一段时间以来&#xff0c;它一直是脚手架 Vue.js 项目的事实标准。不过现在&#xff0c;Evan You的下一代构建工具Vite已经引起了很…

精选7个 Python 学习资源库,助你成为优秀的开发者

当你在学习编程时&#xff0c;很容易被大量的资源所吓到&#xff0c;不知道该从何开始。 GitHub 仓库是一个很好的起点&#xff0c;因为它们提供了一种非常实用的方式来了解实际的编程应用。你可以查看其他人的代码&#xff0c;并将其与自己的代码进行比较和学习。 当涉及到 …

kubernetes(k8s)为容器和 Pod 分配内存资源

kubernetes(k8s)为容器和 Pod 分配内存资源 展示如何将内存请求&#xff08;request&#xff09;和内存限制&#xff08;limit&#xff09;分配给一个容器。 我们保障容器拥有它请求数量的内存&#xff0c;但不允许使用超过限制数量的内存。 创建新的命名空间 kubectl creat…

【数据结构】顺序栈的C语言实现

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;数据结构 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录栈1. 栈的概念1.1 栈…

Java打开CSV文件到JTable展示

概述主要知识点SwingNode类 &#xff1a;把Java swing组件封装成一个JavaFX的Node&#xff0c;使得Java Swing可以和JavaFX嵌套在一起使用&#xff0c;JavaSwing贼丑&#xff0c;但操作简单&#xff0c;JavaFX的表格组件&#xff08;TableView等&#xff09;有点复杂&#xff0…

DevOps流水线搭建-PHP版本

一、介绍流水线发布代码1、官网https://www.jenkins.io/zh2、kubesphere里的介绍https://kubesphere.io/zh/docs/v3.3/devops-user-guide/how-to-use/pipelines/choose-jenkins-agent/3、git仓库可以自己写点测试代码&#xff0c;提交&#xff0c;待会测试用https://gitee.com/…

Mybatis(四):自定义映射resultMap

自定义映射resultMap前言一、处理字段和属性的映射关系问题&#xff1a;方案一&#xff1a;使用别名方案二&#xff1a;在mybatis-config.xml中设置mapUnderscoreToCamelCase方案三&#xff1a;在映射文件中设置redultMap二、多对一映射处理问题&#xff1a;方案一&#xff1a;…

如何在 Vue 中使用 防抖 和 节流

大厂面试题分享 面试题库前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库 https://mp.weixin.qq.com/s?__bizMzU5NzA0NzQyNg&mid2247485824&idx3&sn70cd26a7c0c683de64802f6cb9835003&scene21#wech…

内存操作函数

前言 &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&#x1f32f; c语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f349;本篇简介:>:介绍c语言中有关指针更深层的知识. 金句分享: ✨未来…

蓝桥杯Web前端练习-----渐变色背景生成器

介绍 相信做过前端开发的小伙伴们对渐变色在 UI 设计中的流行度一定不陌生&#xff0c;网页上也时常可以看到各类复杂的渐变色生成工具。使用原生的 CSS 变量加一些 JS 函数就能做出一个简单的渐变色背景生成器。 现在渐变色生成器只完成了颜色选取的功能&#xff0c;需要大家…

【你不知道的 CSS】你写的 CSS 太过冗余,以至于我对它下手了

:is() 你是否曾经写过下方这样冗余的CSS选择器: .active a, .active button, .active label {color: steelblue; }其实上面这段代码可以这样写&#xff1a; .active :is(a, button, label) {color: steelblue; }看~是不是简洁了很多&#xff01; 是的&#xff0c;你可以使用…