一、题目链接:. - 力扣(LeetCode)
二、题目解决代码
typedef int QDataType;
// 链式结构:表示队列
typedef struct QListNode
{
struct QListNode* next;
QDataType data;
}QNode;
// 队列的结构
typedef struct Queue
{
QNode* front; //指向队列的第一个结点
QNode* rear;//指向队列的最后一个结点
int size;//记录队列中一共有几个元素
}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);
// 初始化队列
void QueueInit(Queue* q)
{
assert(q);
q->front = NULL; //初始化为NULL
q->rear = NULL;//初始化为NULL
q->size = 0; //初始化个数为0
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q);
QNode* newnode = (QNode*)malloc(sizeof(QNode));//申请新的结点
if (newnode == NULL)
{
perror("malloc fail");
return;
}
else
{
newnode->data = data;
newnode->next = NULL;
if (q->front == NULL) //如果front指针指向的是NULL,说明插入前队列是空队列
{
q->front = newnode;
q->rear = newnode;
}
else //front指向的不是NULL,说明不是空队列
{
q->rear->next = newnode;
q->rear = newnode;
}
q->size++; //插入完,个数加1
}
}
// 队头出队列
void QueuePop(Queue* q)//出队就是头删
{
assert(q);
assert(q->size != 0);//队列不为空
QNode* head = q->front; //找到头结点
if (head->next == NULL)//如果出队之前,前队列只有一个结点
{
free(head); //释放头结点,后front 和rear都要指向NULL,表示现在是空队列
head = NULL;
q->front = q->rear = NULL;
q->size = 0; //个数置为0
return;
}
else //出队前,队列有两个及其以上的结点数
{
QNode* del = head;
head = head->next; //更新头结点
free(del);
del = NULL;
q->front = head; //将front 指向更新后的头结点
q->size--;//个数减1
}
}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);
return q->front->data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);
return q->rear->data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
assert(q);
return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
assert(q);
if (q->front == NULL)//队列为空,返回1
return 1;
else
return 0;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
assert(q);
QNode* del = q->front; //如果是空队列,就直接返回NULL,不要释放结点
if (del == NULL)
{
;
}
else
{
QNode* cur = del->next;
while (del != NULL) //逐个释放结点
{
free(del);
del = cur;
if (cur != NULL)
cur = cur->next;
}
}
//队头指针和队尾指针都是要置NULL的,size都是要置为0
q->front = q->rear = NULL;
q->size = 0;
}
typedef struct {
Queue A; //创建A队列
Queue B; //创建B队列
} MyStack;
//创建栈,并且初始化
MyStack* myStackCreate() {
MyStack* stack = (MyStack*)malloc(sizeof(MyStack));
if (stack == NULL)
{
perror("malloc fail");
return NULL;
}
QueueInit(&stack->A);//初始化A队列
QueueInit(&stack->B);//初始化B队列
return stack;
}
//压栈
void myStackPush(MyStack* obj, int x) {
if (!QueueEmpty(&obj->A))//如果A队列不为空
{
QueuePush(&obj->A, x);//入A队的队尾
}
else//如果B队列不为空
{
QueuePush(&obj->B, x);//入B队的队尾
}
}
//出栈
int myStackPop(MyStack* obj) {
if (!QueueEmpty(&obj->A))//如果A队列不为空
{
int count = obj->A.size - 1; //从A队列中,将前size-1个元素出队,并依次入队到B队列中
while (count--)
{
int x = QueueFront(&obj->A);//获取A队头元素
QueuePop(&obj->A);//出A队
QueuePush(&obj->B, x);//入B队
}
int y = QueueFront(&obj->A);//获取A队最后一个元素
QueuePop(&obj->A);//再将A队列中的最后一个元素删除
return y;
}
else //如果B队列不为空
{
int count = obj->B.size - 1; //从B队列中,将前size-1个元素出队,并依次入队到A队列中
while (count--)
{
int x = QueueFront(&obj->B);//获取B队头元素
QueuePop(&obj->B);//出B队
QueuePush(&obj->A, x);//入A队
}
int y = QueueFront(&obj->B);//获取B队最后一个元素
QueuePop(&obj->B);//再将B队列中的最后一个元素删除
return y;
}
}
//取栈顶元素
int myStackTop(MyStack* obj) {
if (!QueueEmpty(&obj->A))//如果A队列不为空
{
return obj->A.rear->data; //返回A队列的最后一个元素,就是栈的栈顶元素
}
else //如果B队列不为空
{
return obj->B.rear->data; //返回B队列的最后一个元素,就是栈的栈顶元素
}
}
//判断是否空
bool myStackEmpty(MyStack* obj) {
if (QueueEmpty(&obj->A) && QueueEmpty(&obj->B))
return true;
else
return false;
}
//销毁栈
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->A);//释放A队列
QueueDestroy(&obj->B);//释放B队列
free(obj);//释放申请的stack
}
三、思路方法
1.有两个栈,每次 元素 入队的时候 插入数据在已经有数据的栈中
假设有数据的是A栈,没有元素的是B栈
2.元素出队时,是将有将存储了数据的栈(A栈)里面的元素依次出栈并依次入栈到另一个开始没存储数据的栈(B栈)中
(A栈每顺序出栈一次,就入栈到B栈中,这时,B栈里面的数据存储的数据的顺序就刚好与原来A栈里面的数据存储的顺序刚好相反)
此时 A栈为空,B栈有数据,这时B栈的栈顶元素刚好就是, 原来A栈的第一个元素,也就是我们想找到的队列的队头元素
此时将该数据从B栈出栈,返回该数据,就得到了我们的队头元素
现在我们要将B栈里面的元素再依次出栈,并入栈到A栈之中,恢复到A栈有数据元素,B栈为空的时候