用两个队列实现一个栈and用两个栈实现一个队列

目录

一、用两个队列实现一个栈

1.1 问题描述

1.2 问题分析

1.3 代码

二、用两个栈实现一个队列

2.1 问题描述

2.2 问题分析

2.3 代码


一、用两个队列实现一个栈

1.1 问题描述

oj链接:225. 用队列实现栈 - 力扣(LeetCode)

1.2 问题分析

     用两个队列来实现栈,首先我们需要了解栈和队列这两种结构各自的特点,栈要求先入后出,队列要求先进先出。

     也就是说,用两个队列来模拟实现栈,主要是使用两个队列来完成先入后出的功能,而队列的特点是先入先出,在这里我们主要说明的是入栈和出栈操作:

对于入栈:

对于出栈:

总结起来即以下几点:

  1.  定义一个结构体Stack,包含两个队列q1和q2。
  2.  初始化栈时,分别初始化两个队列。
  3.  入栈操作时,将元素插入非空的队列中。
  4.  出栈操作时,将非空队列中的元素依次出队并插入另一个空队列中,直到只剩下一个元素,然后将该元素出队即可。
  5.  取栈顶元素时,将非空队列中的元素依次出队并插入另一个空队列中,直到只剩下一个元素,然后返回该元素即可。
  6.  判断栈是否为空时,判断两个队列是否都为空即可。

1.3 代码

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)
{
	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->head = pq->tail = NULL;
	pq->size = 0;
}

//入队列
void QueuePush(Queue* pq, QDatatype x)
{
	assert(pq);

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

//判断是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}

//出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!(QueueEmpty(pq)));
	if (pq->head == pq->tail)
	{
		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;
}

//返回队首元素
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;
}

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




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

bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}

int myStackPop(MyStack* obj) {
    assert(!myStackEmpty(obj));
    Queue* nonemptyque = &obj->q1;
    Queue* emptyque = &obj->q2;

    if(QueueEmpty(&obj->q1))
    {
        nonemptyque = &obj->q2;
        emptyque = &obj->q1;
    }

    while(QueueSize(nonemptyque)>1)
    {
        QueuePush(emptyque,QueueFront(nonemptyque));
        QueuePop(nonemptyque);
    }
    int x = QueueFront(nonemptyque);
    QueuePop(nonemptyque);
    return x;
}

int myStackTop(MyStack* obj) {
    assert(!myStackEmpty(obj));
    Queue* nonemptyque = &obj->q1;
    Queue* emptyque = &obj->q2;

    if(QueueEmpty(&obj->q1))
    {
        nonemptyque = &obj->q2;
        emptyque = &obj->q1;
    }
    return QueueBack(nonemptyque);
}



void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);
}

二、用两个栈实现一个队列

2.1 问题描述

oj链接:232. 用栈实现队列 - 力扣(LeetCode)

2.2 问题分析

     我们要用两个栈来实现一个队列,栈的特点是先入后出,队列的特点是先入先出,我们这里的目的是使用两个栈达到先入先出的目的。

     与之前的用两个队列来实现栈,用两个栈来实现队列相对简单,在之前的用两个队列来实现栈,我们在出栈时需要把两个队列中的数据来回翻转,但在本题中,我们只需要定义一个栈来进行插入操作,一个用来删除。

     我们固定使用栈q1来进行入队操作,使用栈q2来进行出队操作。

入队时:

     直接将数据插入到q1中。

出队时:

当q2为空时,再次将q1中数据依次出栈,然后依次插入到栈q2中。

具体总结如下:

  1. 定义一个结构体Queue,包含两个栈s1和s2。
  2. 初始化队列时,分别初始化两个栈。
  3. 入队操作时,将元素插入非空的栈s1中。
  4. 出队操作时,如果栈s2为空,则将栈s1中的元素依次出栈并插入栈s2中,然后将栈s2的栈顶元素出栈即可。
  5. 取队首元素时,如果栈s2为空,则将栈s1中的元素依次出栈并插入栈s2中,然后返回栈s2的栈顶元素即可。
  6. 判断队列是否为空时,判断两个栈是否都为空即可。

2.3 代码

typedef int  STDataType;
#define N 4
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void STInit(ST* ps);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
int STsize(ST* ps);
bool STEmpty(ST* ps);
STDataType STTop(ST* ps);

//初始化函数
void STInit(ST* ps)
{
	assert(ps);
	ps->a = (STDataType*)malloc(sizeof(STDataType)*N);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	
	ps->top = 0;
	ps->capacity = N;
}

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

//求栈中的元素
int STsize(ST* ps)
{
	assert(ps);
	return ps->top;
}

//入栈
void STPush(ST* ps, STDataType x)
{
	assert(ps);
	if (STsize(ps) == ps->capacity)
	{
		STDataType* p = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
		if (p == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->a = p;
		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--;
}

//取出栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}


typedef struct {
    ST q1;
    ST q2;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* pst = (MyQueue*)malloc(sizeof(MyQueue));
    if(pst==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    STInit(&pst->q1);
    STInit(&pst->q2);
    return pst;
}

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

bool myQueueEmpty(MyQueue* obj) {
    return STEmpty(&obj->q1)&&STEmpty(&obj->q2);
}

int myQueuePop(MyQueue* obj) {
    assert(!myQueueEmpty(obj));
    if(STEmpty(&obj->q2))
    {
        while(STsize(&obj->q1)>0)
        {
            STPush(&obj->q2, STTop(&obj->q1));
            STPop(&obj->q1);
        }
        int x= STTop(&obj->q2);
        STPop(&obj->q2);
        return x;  
    }
    else
    {
        int x= STTop(&obj->q2);
        STPop(&obj->q2);
        return x;
    }
}

int myQueuePeek(MyQueue* obj) {
    assert(!myQueueEmpty(obj));
    if(STEmpty(&obj->q2))
    {
        while(STsize(&obj->q1)>0)
        {
            STPush(&obj->q2, STTop(&obj->q1));
            STPop(&obj->q1);
        }
        int x= STTop(&obj->q2);
        return x;  
    }
    else
    {
        int x= STTop(&obj->q2);
        return x;
    }
}



void myQueueFree(MyQueue* obj) {
     STDestroy(&obj->q1);
     STDestroy(&obj->q2);
     free(obj);
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值