【数据结构】【Leetcode】队列和栈的相互转化

目录

前言

1.用队列实现栈

2.用栈实现队列


前言

我们已经熟悉了栈和队列的基本结构以及它们各自的特点,(还不够熟悉的朋友可以看一下我的另外两篇文章)

队列相关博客:https://blog.csdn.net/m0_73737172/article/details/129908874?spm=1001.2014.3001.5502

栈相关博客:

https://blog.csdn.net/m0_73737172/article/details/129907308?spm=1001.2014.3001.5502

那么接下来我们通过Leetcode中的两道题来实现二者的转化,加深对它们结构的认识。

1.用队列实现栈

 

 思路:要想使用两个队列实现栈,我们首先需要明确二者的性质:队列是先进先出,栈则是后进先出,那么假设我存储的内容是1234,如果是队列,那么假设我要取出一个元素,我取出的是1;如果是栈,那么我取出的是4。这时如果我们想通过队列取出4的话,就需要再用一个队列,先将123存入第二个队列,然后第一个队列只剩下4,再用pop函数即可取出。

ok就按照这个思路,如果我们要取出两个元素,比如34,我们就需要再把3之前的元素存入第一个队列中,同样用pop函数将3从第二个队列中取出。

我们继续这个思路往下走,如果此时我要push数据5和6需要存入哪个队列呢,ok是那个非空队列,那么到这我们就明白了这道题也就是要求我们一个队列存储数据,另一个队列为空,负责在需要出数据时起一个“中转站”的作用。

ok那我们开始代码实现。

由于我们是使用c语言进行实现,所以我们需要先把队列写好:

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

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

void QueueInit(Queue* pq);//初始化
void QueueDestroy(Queue* pq);//销毁
void QueuePush(Queue* pq,QDataType x);//插入
void QueuePop(Queue* pq);//删除
int QueueSize(Queue* pq);//队列大小
bool QueueEmpty(Queue* pq);//判空
QDataType QueueFront(Queue* pq);//取队头数据
QDataType QueueBack(Queue* pq);//取队尾数据

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

void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->tail = pq->head = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDataType x)
{
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	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--;
}

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

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

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

 然后根据Leetcode题目所给的函数进行实现:

typedef struct {
    Queue q1;
    Queue q2;

} MyStack;


MyStack* myStackCreate() {
    MyStack*pst=(MyStack*)malloc(sizeof(MyStack));
    if(pst==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    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) {
    Queue* emptyQ=&obj->q1;
    Queue* nonemptyQ=&obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        emptyQ=&obj->q2;
        nonemptyQ=&obj->q1;
    }
    while(QueueSize(nonemptyQ)>1)
    {
        QueuePush(emptyQ,QueueFront(nonemptyQ));
        QueuePop(nonemptyQ);
    }
    int top=QueueFront(nonemptyQ);
    QueuePop(nonemptyQ);
    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);
}

 

 

2.用栈实现队列

类比用队列实现栈,我们用两个栈来实现队列,首先我们按照队列实现栈的思路看看是否可行,我们仍然让一个栈为空,另一个栈存入1234,那么如果是队列的话,要取出一个元素则为1,那么我们按照栈的性质,需要先将234存到另一个栈中,此时即可把1取出,那么此时如果我们要继续取出元素呢,按照队列依次取出的是234,那么我们现在看存有数据的那个栈会发现,234相比之前倒置了,也就是我们直接将第二个栈中的数据依次取出即可,不需要像之前用队列实现栈那样需要不断地转置。 

那么我们继续思考,如果此时我们要继续往进存数据比如56呢,思考一下我们需要再将原先的234倒回另一个栈中吗?如果不倒的话会不会乱呢?

答案是不需要倒回去,我们可以直接将需要插入的数据56存入空栈中,也就是我们现在将原先的空栈只用来存放数据,需要push数据就存入栈A(为了方便我们将该栈记作栈A,另一个记作栈B),需要pop数据就对栈B进行操作,当栈B中的数据都pop之后,如果还要pop就将栈A中的数据存入栈B中,继续如上操作即可。

 

 有了上面的思路我们就可以开始代码实现了:

我们还是需要先将栈的基本结构写好:

typedef int STDataType;
typedef struct Stack
{
	int* a;
	int top;
	int capacity;
}ST;

void STInit(ST* ps);//初始化
void STPush(ST* ps, STDataType x);//插入
void STPop(ST* ps);//删除
int STSize(ST* ps);//栈的大小
bool STEmpty(ST* ps);//判空
void STDestroy(ST* ps);//销毁
STDataType STTop(ST* ps);//访问栈顶元素

void STInit(ST* ps)
{
	assert(ps);
	ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps->capacity = 4;
	ps->top = 0;
}

void STDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

void STPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * ps->capacity * 2);
		if (ps->a == NULL)
		{
			perror("calloc fail");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
	ps->a[ps->top] = x;
	ps->top++;
}

bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}

接下来就是题目所给的函数实现:

typedef struct {
    ST pushst;
    ST popst;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
    if(obj==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    STInit(&obj->pushst);
    STInit(&obj->popst);
    return obj;
}

void myQueuePush(MyQueue* obj, int x) {
    STPush(&obj->pushst,x);
}

int myQueuePop(MyQueue* obj) {
    if(STEmpty(&obj->popst))
    {
        while(!STEmpty(&obj->pushst))
        {
            STPush(&obj->popst,STTop(&obj->pushst));
            STPop(&obj->pushst);
        }
    }
    int front=STTop(&obj->popst);
    STPop(&obj->popst);
    return front;
}

int myQueuePeek(MyQueue* obj) {
    if(STEmpty(&obj->popst))
    {
        while(!STEmpty(&obj->pushst))
        {
            STPush(&obj->popst,STTop(&obj->pushst));
            STPop(&obj->pushst);
        }
    }
    int fornt=STTop(&obj->popst);
    return fornt;
}

bool myQueueEmpty(MyQueue* obj) {
    return STEmpty(&obj->pushst)&&STEmpty(&obj->popst);
}

void myQueueFree(MyQueue* obj) {
    STDestroy(&obj->pushst);
    STDestroy(&obj->popst);
    free(obj);
}

 到这呢我们这两个题目的解答就结束了,你对栈和队列掌握了么?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值