用队列实现栈 和 用栈实现队列(LeetCode)

大家好!这篇我给大家讲两个非常经典的题,希望这两个题能让你对栈和队列的理解更深。
在这里插入图片描述
用队列实现栈:

难度 简单 OJ链接
在这里插入图片描述
因为我们是C语言来做这道题,所以我们需要先写个栈。

因为题目中说是用两个队列,所以:
解题思路:
1.入数据,往不为空的队列入,保持另一个队列为空。
2.出数据,把不为空的队列的数据前N-1导入另外一个空队列,当剩下最后一个时,删掉。

入数据:
在这里插入图片描述
出数据:
在这里插入图片描述
然后,我们看一下题中的这个函数:

MyStack* myStackCreate() {

}

这个函数意思是调用函数来创建结构体,返回这个结构体的指针。

可能会有人这样来写:

MyStack* myStackCreate() {
	MyStack st;
	//......
	return &st;
}

这个不对的,因为局部变量是在栈上创建的,函数结束时,会销毁,所以会变为野指针。

所以我们应该这样写:

MyStack* myStackCreate() {

    MyStack* st=(MyStack*)malloc(sizeof(MyStack));

    //用函数初始化队列
    QueueInit(&st->q1);
    QueueInit(&st->q2);

    return st;
}

图应该这样:
在这里插入图片描述
下面我们来看myStackPush函数:

void myStackPush(MyStack* obj, int x) {
    assert(obj);

    //如果q1不为空,我们在q1Push,否则q2Push
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);

    }

}

如果都为空,我们随便在那个队列插入。

myStackPop函数:

int myStackPop(MyStack* obj) {
    //假设q1为空,q2不为空
    Queue* emptyQ=&obj->q1;
    Queue* nonEmptyQ=&obj->q2;

    //如果假设不成立,进行修改
    if(!QueueEmpty(&obj->q1))
    {
        emptyQ=&obj->q2;
        nonEmptyQ=&obj->q1;
    }

    //把非空的队列前N-1个数据导入空队列
    while(QueueSize(nonEmptyQ)>1)
    {
        QDataType front=QueueFront(nonEmptyQ);
        QueuePush(emptyQ,front);

        //将非空队列的队头删除
        QueuePop(nonEmptyQ);
    }

    QDataType top=QueueFront(nonEmptyQ);
    QueuePop(nonEmptyQ);

    return top;

}

题目中要我们返回栈顶元素。

然后看myStackTop函数:
取栈顶的元素非常简单,我们只需要看那个队列不为空,然后取队尾的那个数据。

int myStackTop(MyStack* obj) {
    assert(obj);

    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    else
    {
        return QueueBack(&obj->q2);

    }
}

myStackEmpty函数:
两个队列必须都为空,我们的栈才为空:

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

myStackFree函数:

void myStackFree(MyStack* obj) {
    assert(obj);
    //销毁队列
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
	
	//销毁包含队列的结构体
    free(obj);

}

在这里,我们不能只 free(obj),我们还要销毁队列,不然会造成内存泄漏。
在这里插入图片描述

完整代码如下:

typedef int 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 QueueDestroy(Queue* pq)
{
	assert(pq);
	
	QueueNode* cur = pq->head;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
}


//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->tail == NULL;
}



//插入函数的定义
void QueuePush(Queue* pq,QDataType x)
{
	assert(pq);

	//创建一个节点
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		printf("malloc is fall\n");
		exit(-1);
	}
	else
	{
		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(!QueueEmpty(pq));

	QDataType* next = pq->head->next;
	free(pq->head);
	pq->head = next;

	if (pq->head == NULL)
	{
		pq->tail = NULL;
	}
	
}


//取队头数据
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;
}


//队列里有多少数据
int QueueSize(Queue* pq)
{
	assert(pq);

	int n = 0;
	QueueNode* cur = pq->head;

	while (cur)
	{
		n++;
		cur = cur->next;
	}

	return n;
}


typedef struct {
    Queue q1;
    Queue q2;
} MyStack;


//调用一个函数来创建结构体,返回这个结构体的指针
MyStack* myStackCreate() {

    MyStack* st=(MyStack*)malloc(sizeof(MyStack));

    //用函数初始化队列
    QueueInit(&st->q1);
    QueueInit(&st->q2);

    return st;
}

void myStackPush(MyStack* obj, int x) {
    assert(obj);

    //如果q1不为空,我们在q1Push,否则q2Push
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);

    }

}

int myStackPop(MyStack* obj) {
    assert(obj);

    //假设q1为空,q2不为空
    Queue* emptyQ=&obj->q1;
    Queue* nonEmptyQ=&obj->q2;

    //如果假设不成立,进行修改
    if(!QueueEmpty(&obj->q1))
    {
        emptyQ=&obj->q2;
        nonEmptyQ=&obj->q1;
    }

    //把非空的队列前N-1个数据导入空队列
    while(QueueSize(nonEmptyQ)>1)
    {
        QDataType front=QueueFront(nonEmptyQ);
        QueuePush(emptyQ,front);

        //将非空队列的队头删除
        QueuePop(nonEmptyQ);
    }

    QDataType top=QueueFront(nonEmptyQ);
    QueuePop(nonEmptyQ);

    return top;

}

int myStackTop(MyStack* obj) {
    assert(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) {
    assert(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);
*/

用栈实现队列:
难度 简单 OJ链接
在这里插入图片描述
因为我们是C语言来做这道题,所以我们需要先写个队列。

因为题目中说是用两个队列,所以:

入数据:
在这里插入图片描述
出数据:
在这里插入图片描述
你会发现,你出数据出的就是1,2,3,我们不需要再导入另外的栈了。

解题思路:
1.我们固定一个入栈的PushST,一个固定的出栈PopST。
2.入数据,只在PushST里入,出数据,我们只在PopST出,当出完时,再把PushST里的数据导入PopST

在这里,我们有了前面的基础,希望大家能够自己去写一下,我们主要来看一下代码:

typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;
	int top;//记录栈顶
	int capacity;
}ST;


//初始化定义
void StackInit(ST* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->top = 0;
	ps->capacity = 0;
}


//销毁函数的定义
void StackDestroy(ST* ps)
{
	assert(ps);
	free(ps->arr);
	ps->arr = NULL;
	ps->top = 0;
	ps->capacity = 0;
}


//栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}


//插入函数的定义
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->arr, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc is fall\n");
			exit(-1);
		}
		else
		{
			ps->arr = tmp;
			ps->capacity = newcapacity;
		}
	}
	ps->arr[ps->top] = x;
	ps->top++;
}



//删除函数的定义
void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	ps->top--;
}



//取栈顶的数据
STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->arr[ps->top - 1];
}

//栈里数据的个数
int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}



typedef struct {
    ST pushST;
    ST popST;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* q=(MyQueue*)malloc(sizeof(MyQueue));

    //将两个栈初始化
    StackInit(&q->pushST);
    StackInit(&q->popST);

    return q;

}

void myQueuePush(MyQueue* obj, int x) {
    assert(obj);
    StackPush(&obj->pushST,x);

}

int myQueuePop(MyQueue* obj) {
    assert(obj);
    //如果popST为空,把pushST导过来,就符合先进先出的顺序了
    if(StackEmpty(&obj->popST))
    {
        //判断pushST是否为空
        while(!StackEmpty(&obj->pushST))
        {
            StackPush(&obj->popST,StackTop(&obj->pushST));
            StackPop(&obj->pushST);
        }
    }

    STDataType front = StackTop(&obj->popST);
    StackPop(&obj->popST);

    return front;

}

int myQueuePeek(MyQueue* obj) {
        assert(obj);
    //如果popST为空,把pushST导过来,就符合先进先出的顺序了
    if(StackEmpty(&obj->popST))
    {
         //判断pushST是否为空
        while(!StackEmpty(&obj->pushST))
        {
            StackPush(&obj->popST,StackTop(&obj->pushST));
            StackPop(&obj->pushST);
        }
    }

    return StackTop(&obj->popST);

}

bool myQueueEmpty(MyQueue* obj) {

    assert(obj);

    return StackEmpty(&obj->pushST)&&StackEmpty(&obj->popST);

}

void myQueueFree(MyQueue* obj) {
    assert(obj);

    StackDestroy(&obj->pushST);
    StackDestroy(&obj->popST);

    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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学代码的咸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值