232. 用栈实现队列

题目:如下文

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false

答案:如下图

typedef int STDataType;

typedef struct Stack
{
	STDataType* _a;
	int _top;//栈顶
	int _capacity;
}Stack;//Stack为结构体
//初始化和销毁
void StackInit(Stack* pst);
void StackDestory(Stack* pst);
//入栈
void StackPush(Stack* pst, STDataType x);
//出栈
void StackPop(Stack* pst);
//获取栈的个数(必定为整数int类型的故采用int)
int StackSize(Stack* pst);
//判断栈是否为空,为空返回1,不为空返回0(0和1一定为整形类型的采用int)
int StackEmpty(Stack* pst);
//获取栈顶的值(一个栈顶的数值有可能不为int类型的,有可能为double类型的,
// 即不为整数,有小数或则其他运算值
STDataType StackTop(Stack* pst);



//初始化和销毁
void StackInit(Stack* pst)
{
	//断言指针是否为空,为空直接报错,不为空才可以接收进行访问;
	assert(pst);
	pst->_a = malloc(sizeof(STDataType) * 4);
	pst->_top = 0;
	pst->_capacity = 4;
}
void StackDestory(Stack* pst)
{
	assert(pst);

	free(pst->_a);
	pst->_a = NULL;
	pst->_capacity = pst->_top = 0;
}
//入栈
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);

	//增容问题

	//realloc()函数的使用条件是在已经创建出的内存下进行修改内存的操作
	//TDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);

	if (pst->_top == pst->_capacity)
	{
		pst->_capacity *= 2;
		STDataType* tmp = (STDataType*)realloc(pst->_a, sizeof(STDataType) * pst->_capacity);
		if (tmp == NULL)
		{
			printf("内存不足\n");
			exit(-1);
		}
		else
		{
			pst->_a = tmp;
		}

	}

	pst->_a[pst->_top] = x;
	pst->_top++;
}
//出栈(正确)
void StackPop(Stack* pst)
{
	assert(pst);
	assert(pst->_top > 0);

	--pst->_top;
}
//获取栈的个数(正确)
int StackSize(Stack* pst)
{
	assert(pst);
	return pst->_top;
}
//判断栈是否为空,为空返回1,不为空返回0(正确)
int StackEmpty(Stack* pst)
{
	assert(pst);

	return pst->_top == 0 ? 1 : 0;
}
//获取栈顶的数据,首先要确保栈顶是有数据的
STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(pst->_top > 0);
	return pst->_a[pst->_top - 1];
}



typedef struct {
	Stack _pushST;
	Stack _popST;
} MyQueue;

//创建栈初始化返回
MyQueue* myQueueCreate() {
	MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
	StackInit(&q->_popST);
	StackInit(&q->_pushST);

	return q;
}
//入栈
void myQueuePush(MyQueue* obj, int x) {
	StackPush(&obj->_pushST, x);
}
//出栈并删除
int myQueuePop(MyQueue* obj) {
	int front = myQueuePeek(obj);
	StackPop(&obj->_popST);
	return front;
}
//出栈且数据不动
int myQueuePeek(MyQueue* obj) {
	if (!StackEmpty(&obj->_popST))
	{
		return StackTop(&obj->_popST);
	 }
	else
	{
		while (!StackEmpty(&obj->_pushST))
		{
			StackPush(&obj->_popST, StackTop(&obj->_pushST));
			StackPop(&obj->_pushST);
		}
		return StackTop(&obj->_popST);
	}
}

bool myQueueEmpty(MyQueue* obj) {
	return StackEmpty(&obj->_popST) && StackEmpty(&obj->_pushST);
}

void myQueueFree(MyQueue* obj) {
	StackDestory(&obj->_popST);
	StackDestory(&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);
*/

解析:

(1)引用栈的源代码

代码过长见答案

题目是用栈实现队列,这里我们可以使用我们自己栈的接口来进行实现更为好操作

(2)定义两个栈,_push和_pop,两者可以倒换进而达到实现队列先进先出的作用

typedef struct {
    Stack _pushST;
    Stack _popST;
} MyQueue;

      ---->         

1)向push中依次储存1,2,3,4

2)通过将push的值由栈的后进先出的逻辑由4到1分别进入pop中

3)pop中top值依次取出符合队列先进先出的逻辑

(3)创建栈并初始化后返回


MyQueue* myQueueCreate() {
    MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&q->_popST);
    StackInit(&q->_pushST);

    return q;
}

初始化开辟空间q

初始化_popST和_pushST

返回q

(4)使用自己接口实现储存数据至_pushST中
void myQueuePush(MyQueue* obj, int x) {
    StackPush(&obj->_pushST, x);

调用自己的接口用指针obj访问_push将数据x储存

(5)出队列且数据不删除

int myQueuePeek(MyQueue* obj) {
    if (!StackEmpty(&obj->_popST))
    {
        return StackTop(&obj->_popST);
     }
    else
    {
        while (!StackEmpty(&obj->_pushST))
        {
            StackPush(&obj->_popST, StackTop(&obj->_pushST));
            StackPop(&obj->_pushST);
        }
        return StackTop(&obj->_popST);
    }
}

 由于这是一个出队列接口所以我们无法确定popST中是否由数据,然而popST中数据符合逻辑上队列先进先出的逻辑,故我们可以直接使用接口StackTop()读取栈的顶端值并使用return进行返回

(6)判断是队列是否为空

bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->_popST) && StackEmpty(&obj->_pushST);
}

首先当且仅当两个栈_popST _pushST都为空时,队列中才没有数据,才为空,故这里我们可以使用&&通过我们自己的接口StackEmpty()函数来进行判断为空则返回1

当并且运算符当且仅当1&&1时运算结果为1,其余情况皆是0,由于是bool类型的值,return 1为ture,reutrn 0为false

(7)释放队列

void myQueueFree(MyQueue* obj) {
    StackDestory(&obj->_popST);
    StackDestory(&obj->_pushST);

    free(obj);
}

这里我们使用自己的接口StackDestory()来摧毁两个栈并且释放obj

到这里我们解题完毕

如果对您有帮助的话点一个免费的赞和收藏叭!

由于本人水平不足,如果有任何错误,麻烦读者评论在评论区指点一下作者,谢谢

  • 33
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值