【数据结构】队列OJ题《用队列实现栈》(题库+解析+代码)

1.前言 

通过前面队列的实现和详解大家对队列应该有一定熟悉了,现在上强度开始做题吧

队列详解:http://t.csdnimg.cn/dvTsW

2.OJ题目训练225. 用队列实现栈

题目分析

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

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

  • 你只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

顾名思义,题目很好理解,那么该如何用队列实现栈呢,单纯用一个队列,那完全是不可能实现栈的,那么我们就要思考如果多一个队列可不可以实现:

方法

如图是两个队列和一个栈按顺序放入数据(1,2,3,4)

如果要实现栈,那么我们第一个拿出的数据就应该是4(后进先出),而如果是队列,第一个拿出的数据则是1(先进先出)

所以我们应该利用好q2(第二个队列)来实现栈相同的效果,实现可以把除4(最后放入队列的数),其他数均放置入q2。

再把q1的4给输出,就能达到栈的效果了

最后输出q1滞空,这样实现一个空队列,一个非空队列来进行不断的交换传输数据

注意要点

  1. 本题目需要借助原本以写过的代码来进行完成,所以请优先查看本文头部的队列教学
  2. 两个队列应该明确好:空队列输入数据,非空输出数据

附源代码

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

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

typedef struct Queue		//由于每次操作的函数都需要传递头和尾指针,所以直接封装更方便
{
	QNode* head;
	QNode* tail;
	int size;
}Que;

void QueueInit(Que* pq);
void QueueDestroy(Que* pq);
void QueuePush(Que* pq, QDataType x);
void QueuePop(Que* pq);
QDataType QueueFront(Que* pq);
QDataType QueueBack(Que* pq);
bool QueueEmpty(Que* pg);
int QueueSize(Que* pg);


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

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

}


void QueueDestroy(Que* 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(Que* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}

void QueuePop(Que* pq) 
{
	assert(pq);
	assert(!QueueEmpty(pq));
	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(Que* pq)	//头出
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->head->data;
}

QDataType QueueBack(Que* pq)	//尾出
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->tail->data;

}
bool QueueEmpty(Que* pq)
{
	assert(pq);
	return pq->head == NULL;

}
int QueueSize(Que* pq)
{
	assert(pq);
	return pq->size;
}


typedef struct {
    Que q1;
    Que 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) 
{
    Que* empty = &obj->q1;
    Que* nonEmpty = &obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        empty = &obj->q2;
        nonEmpty = &obj->q1;
    }
    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);
*/

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 一本通 OJ 题库的测试数据,通常是用来验证提交的代码在各种情况下的正确性。测试数据可以分为两种类型,手动和自动。 手动测试数据是由题目的出人根据意和数据范围设计的一组数据,用来检测程序的正确性和运行效率。手动测试数据的优点是能够涵盖各种情况,但缺点是数量相对较少,不足以覆盖所有可能的情况。 自动测试数据是由程序自动生成的一组数据,可以生成大量的数据以检测程序的健壮性和效率。自动测试数据的优点是数量大且可以自动生成,但缺点是可能无法覆盖某些特殊情况,导致漏洞。 对于提交的代码,一本通 OJ 题库会对其进行编译和运行,然后与测试数据进行比较,判断代码的正确性和效率。如果代码通过了测试数据,就会被判定为正确,否则会被判定为错误,并给出具体的错误信息,供用户进行调试和改进。 综上所述,一本通 OJ 题库的测试数据是一个重要的组成部分,它可以帮助用户测试代码的正确性和运行效率,提高用户的编程技能,同时也可以帮助出人设计更好的题目,并保证题目的质量和难度。 ### 回答2: 一本通 oj题库是一个在线的程序设计竞赛平台,提供了丰富的编程题目和测试数据。测试数据是用于对程序进行测评的输入和输出数据集合。在题目描述中,会对问进行详细的解释和要求,并提供多组测试数据作为样例,让程序员运行他们的代码,并得到程序的输出结果。 测试数据通常包括正向测试数据和反向测试数据。正向测试数据是指符合题目条件的测试数据,覆盖了大多数情况,测试程序是否正确;而反向测试数据则是用于测试程序是否能够正确处理异常情况。 在使用一本通 oj题库时,程序员不仅需要通过编写算法和程序的方式解决问,还需要通过分析测试数据来判断自己的代码是否正确。而一本通 oj题库的丰富数据集合为程序员提供了充足的测试数据,帮助程序员准确地检测代码中存在的漏洞和错误。 总之,一本通 oj题库提供了全面的测试数据来测试程序员的代码是否满足题目描述和要求,是程序员进行程序设计竞赛、算法练习和编程学习的良好平台。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值