Leetcode — 用栈实现队列&用队列实现栈 (C语言)

一、用栈实现队列:

题目描述:

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

说明:
你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

题目链接


思路分析:

1、建立两个栈,pushST和popST。
2、进队列的数据全都进到pushST栈中,如下图所示。
3、出队列时,分为两种情况:
(1)popST为空时,将pushST栈顶的数据依次进到popST中,并弹出,直到pushST为空时结束。再将popST栈顶的数据弹出。
在这里插入图片描述

(2)popST不为空时,直接弹出popST的栈顶数据即可。
在这里插入图片描述
4、取队头时同理,只是不弹出。


代码实现:

typedef int STDateType;
typedef struct stack//栈用数组实现更简单一点
{
	STDateType* a;
	int size;
	int capacity;
}stack;
void stackInit(stack* pst)
{
	assert(pst);
	pst->a = (STDateType*)malloc(sizeof(STDateType)*4);
	pst->size = 0;
	pst->capacity = 4;
}
void stackDestory(stack* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->size = pst->capacity = 0;
}
//入栈
void stackPush(stack* pst, STDateType x)
{
	assert(pst);
	if (pst->size == pst->capacity)
	{
		pst->capacity *= 2;
		STDateType* tmp = (STDateType*)realloc(pst->a, sizeof(STDateType)*pst->capacity);
		pst->a = tmp;
	}
	pst->a[pst->size] = x;
	pst->size++;
}
//出栈
void stackPop(stack* pst)
{
	assert(pst);
	assert(pst->size > 0);
	pst->size--;
}
int stackEmpty(stack* pst)//返回1是空,返回0是非空
{
	assert(pst);
	return pst->size == 0 ? 1 : 0;
}
//获取栈顶的数据
STDateType stackTop(stack* pst)
{
	assert(pst);
	assert(pst->size > 0);
	return pst->a[pst->size - 1];
}
typedef struct {
    stack pushST;
    stack popST;
} MyQueue;

/** Initialize your data structure here. */

MyQueue* myQueueCreate() {
    MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
    stackInit(&q->pushST);
    stackInit(&q->popST);
    return q;
}

/** Push element x to the back of queue. */
void myQueuePush(MyQueue* obj, int x) {
    stackPush(&obj->pushST, x);
}

/** Removes the element from in front of queue and returns that element. */
int myQueuePop(MyQueue* obj) {
    int front = myQueuePeek(obj);//取队头
    stackPop(&obj->popST);
    return front;
}

/** Get the front element. */
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);
    }
}

/** Returns whether the queue is empty. */
bool myQueueEmpty(MyQueue* obj) {
    if(stackEmpty(&obj->pushST)&&stackEmpty(&obj->popST))
    {
        return true;
    }
    return false;
}

void myQueueFree(MyQueue* obj) {
    stackDestory(&obj->pushST);
    stackDestory(&obj->popST);
    free(obj);
    obj = NULL;
}

二、用队列实现栈:

题目描述:

使用队列实现栈的下列操作:

push(x) – 元素 x 入栈
pop() – 移除栈顶元素
top() – 获取栈顶元素
empty() – 返回栈是否为空

注意:

你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。

题目链接


思路分析:

1、建立两个队列,q1和q2(假设q1不为空,q2为空)
2、入栈时将数据入到不为空的队列中。
3、出栈时,将队列q1中数据依次出队到队列q2中,并弹出,直到队列q1中剩一个数据。将该数据弹出即可。具体步骤如下图所示。
在这里插入图片描述
核心:总有一个队列是为空的。

4、获取栈顶的数据时,取不为空的那个队列的队尾即可。


代码实现:

//只有弹出数据的时候要借助两个队列,取栈顶元素的时候可以直接利用队尾指针即可
typedef char QDataType;
typedef struct queueNode
{
	struct queueNode* next;
	QDataType data;
}queueNode;
typedef struct queue
{
	queueNode* head;
	queueNode* tail;
}queue;
void queueInit(queue* pq)
{
	assert(pq);
	(pq)->head = NULL;
    (pq)->tail = NULL;
}
void queueDestory(queue* pq)
{
	assert(pq);
	queueNode* cur = pq->head;
	while (cur)
	{
		queueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
}
void queuePush(queue* pq, QDataType x)
{
	assert(pq);
	queueNode* newnode = (queueNode*)malloc(sizeof(queueNode));
	newnode->data = x;
	newnode->next = NULL;
	if (pq->head == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}
void queuePop(queue* pq)
{
	assert(pq);
	assert(pq->head);
	queueNode* next = pq->head->next;
	free(pq->head);
	pq->head = next;
	if (pq->head == NULL)
	{
		pq->tail = NULL;
	}
}
QDataType queueFront(queue* pq)
{
	assert(pq);
	assert(pq->head);
	return pq->head->data;
}
QDataType queueBack(queue* pq)
{
	assert(pq);
	assert(pq->tail);
	return pq->tail->data;
}
int queueEmpty(queue* pq)//返回1是空,0是非空
{
	if (pq->head == NULL)
	{
		return 1;
	}
	else return 0;
}
int queueSize(queue* pq)
{
	assert(pq);
	int size = 0;
	queueNode* cur = pq->head;
	while (cur != NULL)
	{
		size++;
		cur = cur->next;
	}
	return size;
}
typedef struct {
    queue q1;
    queue q2;
} MyStack;

/** Initialize your data structure here. */

MyStack* myStackCreate() {
    MyStack* obj =(MyStack*)malloc(sizeof(MyStack)); 
    queueInit(&obj->q1);
    queueInit(&obj->q2);
    return obj;
}

/** Push element x onto stack. */
void myStackPush(MyStack* obj, int x) {
    if(!queueEmpty(&obj->q1))//将数据入到不为空的队列里
    {
        queuePush(&obj->q1,x);
    }
    else
    {
        queuePush(&obj->q2,x);
    }
}

/** Removes the element on top of the stack and returns that element. */
int myStackPop(MyStack* obj) {
    queue* empty = &obj->q1;
    queue* nonEmpty = &obj->q2;
    if(queueEmpty(&obj->q2))//如果q2为空
    {
        empty = &obj->q2;
        nonEmpty = &obj->q1;
    }
    while(queueSize(nonEmpty) > 1)//对非空的队列操作
    {
        queuePush(empty,queueFront(nonEmpty));
        queuePop(nonEmpty);
    }
    int top = queueFront(nonEmpty);
    queuePop(nonEmpty);//把最后一个数据弹掉
    return top;
}

/** Get the top element. */
int myStackTop(MyStack* obj) {
    if(!queueEmpty(&obj->q1))
    {
        return queueBack(&obj->q1);
    }
    else//如果两者都为空,该题不会调用该接口
    {
        return queueBack(&obj->q2);
    }
}

/** Returns whether the stack is empty. */
bool myStackEmpty(MyStack* obj) {
    if(queueEmpty(&obj->q1)&&queueEmpty(&obj->q2))
    {
        return true;
    }
    return false;
}

void myStackFree(MyStack* obj) {
    queueDestory(&obj->q1);
    queueDestory(&obj->q2);
    free(obj);
    obj=NULL;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值