用队列实现栈

目录

1:思路分析

2:栈的实现

3: 队列实现栈

1):定义队列

 2):初始化队列

3):插入数据

3):删除数据

4):取栈顶数据

5): 判空

6):释放

 4:总代码


1:思路分析

1):题目要求我们用两个队列实现栈的出栈、入栈、取栈顶数据等,所以我们可以这里用两个队列来相互导数据,因为队列是先进队列的数据就先出队列,所以我们这里并且保持一个队列存数据,一个队列为空,如下图:

2):入数据就如不为空的队列,导数据就将不为空的队列中的数据导到为空的队列当中去(将q2中的的数据导到q1当中去) ,如果还要入数据的的话就入到q1当中去

2:栈的实现

1):因为我们是用C语言实现,所以需要手搓一下栈,一下是栈的实现代码:

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int QDatatype;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDatatype val;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;


//队的初始化  和  销毁
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
//队的尾插  和  头删
void QueuePush(Queue* pq, QDatatype x);
void QueuePop(Queue* pq);
//取队尾数据  和  队头数据
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);
//队的数据个数
int QueueSize(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);

void QueueInit(Queue* pq)
{
	assert(pq);

	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

//尾插
void QueuePush(Queue* pq, QDatatype x)
{

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->next = NULL;
	newnode->val = x;

	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

void QueueDestory(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);

		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}


void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}

int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);

	return pq->phead->val;
}

QDatatype QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);

	return pq->ptail->val;
}

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}

3: 队列实现栈

1):定义队列

首先我们先定义两个队列,Queue q1 和 Queue q2

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

 2):初始化队列

定义好队列后,我们需要对队列初始化,我们这里可以直接调用栈的初始化QueueInit,对Queue q1 和 Queue q2 进行初始化

MyStack* myStackCreate() {
    MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
    QueueInit(&(pst->q1));
    QueueInit(&(pst->q2));

    return pst;
}

 

3):插入数据

接下来我们实现插入操作,在插入时,我们需要对队列q1进行判空,如果q1不为空,我们就将数据插入到q1中去,(else)q1为空的话,我们就将数据插入到q2中去,因为本题2我们是始终让一个队列不为空,一个队列为空的

 

void myStackPush(MyStack* obj, int x) {
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }
}

3):删除数据

删除操作这里我们可以用一下假设法先假设q1为空(empty),假设q2为非空(nonEmpty),当q1为非空时,那么就说明我们假设错了,则q1为非空(nonEmpty),q2为空(empty)

然后对非空队列(nonEmpty)进行导数据,将非空队列(nonEmpty)的数据导到空队列(empty)当中去,直到队尾的数据时停止导数据(将不为空前szie-1导走,删除最后一个就是顶部数据,保存非空队列(nonEmpty)中的最后一个数,并将其删除(pop)掉,然后返回保存的最后一个数即可

 

int myStackPop(MyStack* obj) {
    //假设法
    Queue* empty = &(obj->q1);//空
    Queue* nonEmpty = &(obj->q2);//非空

    if(!QueueEmpty(&obj->q1))
    {
        nonEmpty = &(obj->q1);
        empty = &(obj->q2);
    }
    //不为空前szie-1导走,删除最后一个就是顶部数据
    while(QueueSize(nonEmpty) > 1)
    {
        QueuePush(empty,QueueFront(nonEmpty));
        QueuePop(nonEmpty);
    }

    int top = QueueFront((nonEmpty));
    QueuePop(nonEmpty);

    return top;
}

4):取栈顶数据

取数据时我们先要判断一下q1和q2,如果是q1不为空,那么q2为空,我们直接返回q1的队尾数据

如果是q2不为空,那么q1为空,我们直接返回q2的队尾数据

 

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

5): 判空

分别队q1和q2进行判空,然后返回q1和q2

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

6):释放

在释放的时候我们不能直接释放栈(free(obj)),因为q1队列中还有szie个元素没有释放掉,如果直接free(obj),那么q1队列中的数就成了野指针,所以我们需要分别释放掉q1和q2,最后再整体释放掉obj

void myStackFree(MyStack* obj) {
    QueueDestory(&(obj->q1));
    QueueDestory(&(obj->q2));

    free(obj);
}

 4:总代码

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

MyStack* myStackCreate() {
    MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
    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* empty = &(obj->q1);//空
    Queue* nonEmpty = &(obj->q2);//非空

    if(!QueueEmpty(&obj->q1))
    {
        nonEmpty = &(obj->q1);
        empty = &(obj->q2);
    }
    //不为空前szie-1导走,删除最后一个就是顶部数据
    while(QueueSize(nonEmpty) > 1)
    {
        QueuePush(empty,QueueFront(nonEmpty));
        QueuePop(nonEmpty);
    }

    int top = QueueFront((nonEmpty));
    QueuePop(nonEmpty);

    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) {
    QueueDestory(&(obj->q1));
    QueueDestory(&(obj->q2));

    free(obj);
}

以上就是用队列实现栈问题的所有思路和分析了,创作不易,求求大家点个小赞赞,感谢各位老们的赏脸观看,随手点个赞,养成好习惯,如有问题,感谢反馈!

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值