leetcode:225. 用队列实现栈

题目

225.用队列实现栈
使用队列实现栈的下列操作:

push(x) --元素 x 入栈
pop() --移除栈顶元素
top() --获取栈顶元素
empty() --返回栈是否为空

注意 :

你只能使用队列的基本操作-- 也就是 push to back, peek / pop from front, size, 和 is empty 这些操作是合法的。
你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列, 只要是标准的队列操作即可。
你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-stack-using-queues

解题思路以及图解

栈的特点:

  • 1、后进先出。
  • 2、栈顶插入,栈顶弹出
  • 3、通常由数组实现

队列的特点:

  • 1、先进先出。
  • 2、队尾插入,队头弹出。
  • 3、通常用链表实现,如果用数组(顺序表)实现,头部弹出时有数据挪动,时间复杂度上升。

如何用队列实现栈呢?
我们可以用两个队列去实现栈,一个队列保持空,一个队列保持非空,非空栈用来插入数据,当需要获取栈顶时,直接获取非空队列队尾数据即可。

但是出栈无法通过正常的队列操作实现,队列只能出队头,此时出栈(最后进来的数据),需要出队尾,该如何操作?

将非空队列的数据,依次出队头再入队尾到空队列,当非空队列剩下最后一个数据时,这个数据就是栈顶(最后进来的)数据。
图解

插入:插入相同,都是从尾插入。
在这里插入图片描述
获取栈顶元素:即获取队尾。
在这里插入图片描述
出栈:出栈顶,出最后进来的数据。

在这里插入图片描述
出栈完成后:原本的空队列变为非空,非空队列清空。下一次出栈依旧从非空队列出。
在这里插入图片描述

代码

typedef int QDataType;
// 链式结构:表示队列
typedef struct QListNode
{
    
    
	struct QListNode* _pNext;
	QDataType _data;
}QNode;
// 队列的结构
typedef struct Queue
{
    
    
	QNode* _front;
	QNode* _tail;
}Queue;
// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);


typedef int QDataType;
// 链式结构:表示队列
typedef struct QListNode
{
    
    
	struct QListNode* _pNext;
	QDataType _data;
}QNode;
// 队列的结构
typedef struct Queue
{
    
    
	QNode* _front;
	QNode* _tail;
}Queue;
// 初始化队列
void QueueInit(Queue* q)
{
    
    
	q->_front = NULL;
	q->_tail = NULL;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
    
    
	QNode* node = (QNode*)malloc(sizeof(QNode));
	if (node)
	{
    
    
		node->_data = data;
		node->_pNext = NULL;
	}
	if (q->_tail == NULL)
	{
    
    
		q->_front = q->_tail = node;
	}
	else
	{
    
    
		q->_tail->_pNext = node;
		q->_tail = node;
	}
}
// 队头出队列
void QueuePop(Queue* q)
{
    
    
	if (q->_front == NULL)
	{
    
    
		return;
	}
	else
	{
    
    
		QNode* temp = q->_front->_pNext;
		free(q->_front);
		q->_front = temp;
		if (temp == NULL)
		{
    
    
			q->_tail = NULL;
		}
	}

}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
    
    
	return q->_front->_data;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
    
    
	if (q->_front == NULL)
	{
    
    
		return 1;
	}
	else
	{
    
    
		return 0;
	}
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
    
    
	return q->_tail->_data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
    
    
	int len = 0;
	QNode* head = q->_front;
	while (head)
	{
    
    
		head = head->_pNext;
		len++;
	}
	return len;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
    
    
	int rel = QueueEmpty(q);
	if (rel)
	{
    
    

	}
	else
	{
    
    
		while (q->_front)
		{
    
    
			QNode *temp = q->_front->_pNext;
			free(q->_front);
			q->_front = temp;
		}
	}
}
typedef struct {
    
    
	Queue List1;
	Queue List2;
} MyStack;

/** Initialize your data structure here. */

MyStack* myStackCreate() {
    
    
	MyStack*st = (MyStack*)malloc(sizeof(MyStack));
	QueueInit(&(st->List1));//传队列的地址,接口中进行初始化
	QueueInit(&(st->List2));
	return st;
}

/** Push element x onto stack. */
void myStackPush(MyStack* obj, int x) {
    
    
	if (!QueueEmpty(&obj->List1))//如果list1不为空,插入到list1.
	{
    
    
		QueuePush(&obj->List1, x);
	}
	else         //此时list2可能为空也可能不为空,
             	//但不影响,只要保保持其中一个队列为空即可
	{
    
    
		QueuePush(&obj->List2, x);
	}
}

/** Removes the element on top of the stack and returns that element. */
int myStackPop(MyStack* obj) {
    
    
	Queue* Empty = &obj->List1;//默认list1为空,
	Queue* NonEmpty = &obj->List2;//默认list2不为空
	if (!QueueEmpty(&obj->List1))//如果与默认相反,再进行调整
	{
    
    
		Empty = &obj->List2;
		NonEmpty = &obj->List1;
	}
	int Top = 0;
	while (QueueSize(NonEmpty)>1)//当非空队列剩下最后一个数据时,
	                             //就是栈顶,也就是最后进入的数据
	{
    
    
		Top = QueueFront(NonEmpty);
		QueuePush(Empty, Top);
		QueuePop(NonEmpty);
	}//依次从非空队列获取队头,再入队尾到空队列,
	Top = QueueFront(NonEmpty);//剩下最后一个数据了,保存它用来返回。
	QueuePop(NonEmpty);//清除,原本的非空队,此时成为空队,
	return Top;
}

/** Get the top element. */
int myStackTop(MyStack* obj) {
    
    
	if (!QueueEmpty(&obj->List1))
	{
    
    
		return QueueBack(&obj->List1);//栈后进先出,队尾是后进的,
		//所以获取栈顶,就是获取最后进来的数据,就是获取非空队列的队尾,
	}
	else
	{
    
    
		return QueueBack(&obj->List2);
	}
}

/** Returns whether the stack is empty. */
bool myStackEmpty(MyStack* obj) {
    
    
	if (QueueEmpty(&obj->List1) && QueueEmpty(&obj->List2))
	{
    
    
		return true;
	}
	else
	{
    
    
		return false;
	}
}

void myStackFree(MyStack* obj) {
    
    
	QueueDestroy(&obj->List1);
	QueueDestroy(&obj->List2);
	free(obj);
}

猜你喜欢

转载自blog.csdn.net/Zhou000815/article/details/112300652