C语言用两个栈实现队列(完整版)
队列是一种 先进先出(first in - first out, FIFO)的数据结构,队列中的元素都从后端(rear)入队(push),从前端(front)出队(pop)。
实现队列最直观的方法是用链表,但在这篇文章里我会介绍另一个方法 - 使用栈。
栈是一种 后进先出(last in - first out, LIFO)的数据结构,栈中元素从栈顶(top)压入(push),也从栈顶弹出(pop)。
为了满足队列的 FIFO 的特性,我们需要用到两个栈,用它们其中一个来反转元素的入队顺序,用另一个来存储元素的最终顺序。
方法一(使用两个栈 入队 - O(n)O(n), 出队 - O(1)O(1))
算法
入队(push)思路:考虑入队的元素是先进先出,后进后出,而你的栈是后进先出,那么你最新压入的元素(后进的)应该在栈底,也就是只要保证后进后出即可
一个队列是 FIFO 的,但一个栈是 LIFO 的。这就意味着最新压入的元素必须得放在栈底。为了实现这个目的,我们首先需要把 s1 中所有的元素移到 s2 中,接着把新元素压入 s2。最后把 s2 中所有的元素弹出,再把弹出的元素压入 s1。
出队(pop)
直接从 s1 弹出就可以了,因为 s1 的栈顶元素就是队列的队首元素。同时我们把弹出之后 s1 的栈顶元素赋值给代表队首元素的 front 变量。
以上图片以及文字来自https://leetcode-cn.com/problems/implement-queue-using-stacks/solution/yong-zhan-shi-xian-dui-lie-by-leetcode/
#include <stdio.h>
#include <stdlib.h>
#define maxsize 100
//创建栈
struct Stack{
int data[maxsize];
int top;
};
typedef struct Stack MyStack;
//队列定义为双栈
typedef struct {
MyStack s1; //S1为主栈
MyStack s2; //S2为用来反转的栈
} MyQueue;
/** Initialize your data structure here. */
MyQueue* myQueueCreate() {
MyQueue * tempQueue =(MyQueue *)malloc(sizeof(MyQueue));
tempQueue->s1.top = -1 ;
tempQueue->s2.top = -1 ;
return tempQueue ;
}
/** Push element x to the back of queue. */
void myQueuePush(MyQueue* obj, int x) {
if(obj->s1.top<maxsize)
{
while(obj->s1.top!=-1) //栈是否满
{
obj->s2.data[++(obj->s2.top)]=obj->s1.data[(obj->s1.top)--];////把S1栈中元素压入S2实现反转
}
obj->s1.data[++(obj->s1.top)]= x ; ////把push的元素压入S1栈(此时S1为空栈,因为它的元素已经全部给S2啦)
while(obj->s2.top!=-1)
{
obj->s1.data[++(obj->s1.top)]=obj->s2.data[(obj->s2.top)--];//再把S2栈中的元素全部反转压入S1
}
}
}
void show_myQueue(MyQueue * obj)
{
int temp =obj->s1.top ;
while(temp!=-1)
{
printf("%d ",obj->s1.data[temp--]);
}
printf("\n");
}
/** Removes the element from in front of queue and returns that element. */
int myQueuePop(MyQueue* obj) {
if(obj->s1.top!=-1)
{
return obj->s1.data[obj->s1.top--] ;
}
// return NULL ;
}
/** Get the front element. */
int myQueuePeek(MyQueue* obj) {
if(obj->s1.top!=-1)
{
return obj->s1.data[obj->s1.top] ;
}
// return NULL ;
}
/** Returns whether the queue is empty. */
bool myQueueEmpty(MyQueue* obj) {
if(obj->s1.top == -1)
return true ;
return false ;
}
void myQueueFree(MyQueue* obj) {
free(obj);
}
int main()
{
int i ;
MyQueue * myQueue =NULL;
myQueue =myQueueCreate();
for(i=0;i<3;i++)
{
myQueuePush(myQueue,i);
}
show_myQueue(myQueue);
printf("出队的元素是:%d\n",myQueuePop(myQueue));
printf("此时队列内的首个的元素是:%d\n",myQueuePeek(myQueue));
}
/**
* 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);
*/
C语言用两个栈实现队列(完整版)的更多相关文章
- 【Java】 剑指offer(8) 用两个栈实现队列
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数append ...
- 剑指Offer面试题:6.用两个栈实现队列
一.题目:用两个栈实现队列 题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能. 原文是使用 ...
- 剑指OFFER之用两个栈实现队列(九度OJ1512)
题目描述: 用两个栈来实现一个队列,完成队列的Push和Pop操作.队列中的元素为int类型. 输入: 每个输入文件包含一个测试样例.对于每个测试样例,第一行输入一个n(1<=n<=100 ...
- 九度OJ 1512 用两个栈实现队列 【数据结构】
题目地址:http://ac.jobdu.com/problem.php?pid=1512 题目描述: 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 输入: 每 ...
- 两个栈实现队列+两个队列实现栈----java
两个栈实现队列+两个队列实现栈----java 一.两个栈实现一个队列 思路:所有元素进stack1,然后所有出s ...
- Algorithm --> 两个栈实现队列和两个队列实现栈
两个栈实现队列和两个队列实现栈 队列(queue)先进先出的线性表:栈(stack)先进后出的线性表. 两个栈实现队列 法一思路: s1是入栈的,s2是出栈的. 入队列:直接压入s1即可: 出队列:如 ...
- 二、 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek)
请指教交流! package com.it.hxs.c01; import java.util.Stack; /* 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek) */ ...
- 两个队列实现栈&两个栈实现队列(JAVA)
1,两个栈实现队列 题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路:栈的特点时先进后出,队列的特点是先进先出. 若此时有两个队列stack1,st ...
- 剑指offer【05】- 用两个栈实现队列(java)
题目:用两个栈实现队列 考点:栈和队列 题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 解题思路:每次psuh是时先将stack2清空放入stck1(保 ...
随机推荐
- springboot-mybatis配置问题
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题
- SystemVerilog搭建APB_I2C IP 层次化验证平台
一.前言 近期疫情严重,身为社畜的我只能在家中继续钻研技术了.之前写过一篇关于搭建FIFO验证平台的博文,利用SV的OOP特性对FIFO进行初步验证,但有很多不足之处,比如结构不够规范.验证组件类不独 ...
- ROS中的3D机器人建模(二)
一,创建我们的第一个URDF模型 我们设计的第一个机器人模型是pan-and-tilt机械结构,代码如下 pan_tilt.urdf: 1 <?xml version="1.0&quo ...
- kvm实现快速增量盘模式的克隆脚本
转自:http://zxlwz.blog.51cto.com/6952946/1852424 要求:备份的img磁盘格式只有qcow2格式支持增量盘使用和快照功能当你的一个虚拟机格式是raw格式时,请 ...
- 关于将笔记本电脑作为wifi热点的详细步骤
常规做法直接度娘.如果出现无法打开wifi功能,可找对应解决方法. 1.先检查网卡是否支持承载网络,检查方法为在cmd中使用管理员权限运行,输入netsh wlan show drivers.查看支持 ...
- MVVM框架(二)---生命周期
一.Vue 生命周期图解: 这张图是官方给出的,大家可能都看过.其中我们重点讲述以下几个钩子函数: beforeCreate --> created beforeMount --> ...
- DBA常用SQL之DDL生成语句-2
------数据迁移常用SQL SELECT 'DROP USER '||u.username ||' CASCADE;' AS dropstrs FROM DBA_USERS U where u.u ...
- Go语言实现:【剑指offer】从上往下打印二叉树
该题目来源于牛客网<剑指offer>专题. 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 不需分层,一维数组. Go语言实现: /** * Definition for a bi ...
- C++:重载前置++/--返回引用,重载后置++/--返回临时对象
标准库中iterator对++/--的重载代码如下: _Myiter& operator++() { // preincrement ++*(_Mybase *)this; return (* ...
- 【学习底层原理系列】重读spring源码1-建立基本的认知模型
开篇闲扯 在工作中,相信很多人都有这种体会,与其修改别人代码,宁愿自己重写. 为什么? 先说为什么愿意自己写: 从0-1的过程,是建立在自己已有认知基础上,去用自己熟悉的方式构建一件作品.也就是说, ...