对栈和队列进行结合

今天刷题卡看到一个将队列和栈结合的一道题,我感觉这到题能是大家对队列和栈能有进一步的了解,但主要还是对队列有进一步的了解

放上题目

这道题是来自力扣上的一道题,这也是博主这几个月没更新的原因,博主因为个人原因刷题去了

https://leetcode.cn/problems/implement-stack-using-queues/

这是这道题的链接

这道题的要求就是让我们利用队列的方式来实现栈的功能。首先我们来说一说栈的特性,栈最主要最让人深知的一个特性就是先进后出,后进先出的原则。队列的原则是从队尾进入从队头出,这很明显不满足栈的功能。

 我们想要利用队列的特性来完成栈的功能,该怎么首先呢?

首先我们得对队列的结构进行选择,我们一般都是选择链表最为队列的结构,这是因为队列的功能链表都能实现。例如对头出数据可以利用链表的头出数据,队尾进数据可以利用链表的尾插来进数据。

我们想要完成这道题的话,肯定不止利用到一个队列,这道题需要两个队列来进行操作处理:

首先一个队列存入数据
另外一个队列空出来

当要出栈顶数据时,将存入数据的队列按头出的方式存入另外一个空的队列中去,直到之前的那个队列剩下一个数据就是栈顶元素
当要进数据时,数据尾插到非空的队列中去才行

typedef int QDataType;

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

typedef struct Queue
{
	QueueNode* head;
	QueueNode* tail;
}Queue;

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

void QueueInit(Queue* pq);
void QueueDestroy(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->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;
}
//队列是对头出数据,队尾进数据
//尾插进数据
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
	node->next = NULL;
	node->data = x;

	if (pq->head == NULL)
	{
		pq->head = pq->tail = node;
	}
	else
	{
		pq->tail->next = node;
		pq->tail = node;
	}
}
//头删出数据
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

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

	if (pq->head == NULL)
	{
		pq->tail = NULL;
	}
	
}	
//返回队头的数据
QDataType QueueFront(Queue* pq)
{
	assert(pq);

	return pq->head->data;
}
//返回队尾的数据
QDataType QueueBack(Queue* pq)
{
	assert(pq);

	return pq->tail->data;
}
//返回这个队列的大小
int QueueSize(Queue* pq)
{
	assert(pq);
	int num = 0;
	QueueNode* cur = pq->head;

	while (cur)
	{
		num++;
		cur = cur->next;
	}
	return num;
}
//判断这个队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->head == NULL;
}

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

    return st;
}

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

int myStackPop(MyStack* obj) {
    //假设q1队列为空,q2队列不为空
    Queue * empty = &obj->q1;
    Queue * notempty = &obj->q2;

    //首先要对两个队列进行判断
    //如果队列q1不为空
    if(!QueueEmpty(&obj->q1))
    {
        empty = &obj->q2;
        notempty = &obj->q1;
    }
    /*
    将不为空的队列以队头出的方式输入到为空的队列中去,直到不为空的队列中只有一个数据停止
    */
    while(QueueSize(notempty) > 1)
    {
        QueuePush(empty,QueueFront(notempty));
        QueuePop(notempty);
    }
    int top = QueueFront(notempty);
    QueuePop(notempty);

    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) {
    /*
    为什么不能直接释放掉obj?因为在这个栈中还有两个队列,如果只是释放放掉栈的空间的话,会导致俩个队列的空间还存留在内存当中,这会导致内存泄漏。所以必须先将两个队列的空间给释放掉,最后在把栈的空间释放
    */
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);
}

猜你喜欢

转载自blog.csdn.net/m0_59083833/article/details/125226071