Leetcode-用队列实现栈
【摘要】 大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流作者简介:CSDN C/C++领域新星创作者https://blog.csdn.net/chuxinchangcun?type=blog掘金LV3用户 https://juejin.cn/u...
大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流
作者简介:
CSDN C/C++领域新星创作者https://blog.csdn.net/chuxinchangcun?type=blog
掘金LV3用户 https://juejin.cn/user/1381426159953960
阿里云社区专家博主,星级博主,技术博主 https://developer.aliyun.com/profile/expert/5lkdbuggiiuhc
华为云云享专家 https://bbs.huaweicloud.com/community/myhomepage
题目
https://leetcode-cn.com/problems/implement-stack-using-queues/

思路:
栈:先进后出
队列:先进先出
保持一个队列为空,另一个队列存放数据
队列中的数据导入到另一个队列:元素插入的顺序不变
接口1:栈的结构
typedef struct {
Queue q1;
Queue q2;
} MyStack;
里面包含两个队列
接口2:初始化
MyStack* myStackCreate() {
//动态开辟一个栈结构体
MyStack* st = (MyStack*)malloc(sizeof(MyStack));
//使用我们自己实现的接口初始化两个队列
QueueInit(&st->q1);
QueueInit(&st->q2);
return st;
}
错误写法
MyStack* myStackCreate() { MyStack st ; return &st; }
st是局部变量,出了函数,空间就被销毁了。st的地址是野指针,返回了已经销毁的栈空间的地址
接口3:插入数据
永远保持一个队列为空

// 入数据
void myStackPush(MyStack* obj, int x) {
//往不为空的队列中入数据
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
接口4: 删除数据
//出数据
int myStackPop(MyStack* obj)
{
//把有数据的队列的数据导入到空队列
//先假设某一个队列不为空,假设队列q1不为空,q2为空
Queue* noemptyQ = &obj->q1;
Queue* emptyQ = &obj->q2;
//如果q2不为空,说明假设反了
if(!QueueEmpty(&obj->q2))
{
emptyQ = &obj->q1;
noemptyQ = &obj->q2;
}
//把不空队列的数据导入到空队列,直到不空队列只剩一个元素
while(QueueSize(noemptyQ) > 1)
{
QueuePush(emptyQ,QueueFront(noemptyQ));
QueuePop(noemptyQ);
}
int top = QueueFront(noemptyQ);
QueuePop(noemptyQ);
return top;
}
接口5:返回栈顶数据

int myStackTop(MyStack* obj)
{
//那个队列有数据,就返回哪个队列的队尾数据
if(!QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q1);
}
else
{
return QueueBack(&obj->q2);
}
}
接口6:判断栈是否为空
如果两个队列都为空->栈为空

bool myStackEmpty(MyStack* obj) {
//如果两个队列都为空->栈为空
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
接口7:释放空间
先调用我们自己写的接口:释放两个队列
然后再释放我们动态开辟的栈结构体

void myStackFree(MyStack* obj)
{
//先释放两个队列
QueueDestory(&obj->q1);
QueueDestory(&obj->q2);
//再释放动态开辟的栈结构体
free(obj);
}
实现的接口
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) {
//往不为空的队列中入数据
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
//出数据
int myStackPop(MyStack* obj)
{
//把有数据的队列的数据导入到空队列
//先假设某一个队列不为空,假设队列q1不为空,q2为空
Queue* noemptyQ = &obj->q1;
Queue* emptyQ = &obj->q2;
//如果q2不为空,说明假设反了
if(!QueueEmpty(&obj->q2))
{
emptyQ = &obj->q1;
noemptyQ = &obj->q2;
}
//把不空队列的数据导入到空队列,直到不空队列只剩一个元素
while(QueueSize(noemptyQ) > 1)
{
QueuePush(emptyQ,QueueFront(noemptyQ));
QueuePop(noemptyQ);
}
int top = QueueFront(noemptyQ);
QueuePop(noemptyQ);
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);
}
总代码
typedef int QDataType;
//队列中的结构体
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QueueNode;
//存放指向结构体的两个指针
typedef struct Queue
{
QueueNode* head;//指向链表的头
QueueNode* tail;//指向链表的尾
}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->head = NULL;
pq->tail = NULL;
}
//销毁
void QueueDestory(Queue* pq)
{
assert(pq);
//链表要遍历销毁结点,不能直接销毁
QueueNode* cur = pq->head;
while (cur)
{
//保存下一个结点
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = NULL;
pq->tail = NULL;
}
//队尾入数据
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
//相当于尾插
//构建新结点
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
newnode->next = NULL;
newnode->data = x;
//情况1:链表为空
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
//情况2:
//tail newnode
else
{
pq->tail->next = newnode; //尾插
//注意如果一开始没有数据,pq->tail = NULL,此时会出错,相当于对空指针解引用
//所以没有数据时需要单独判断
pq->tail = newnode;//指向新的尾
}
}
//队头出数据
void QueuePop(Queue* pq)
{
assert(pq);
//情况1:链表为空
/*if (pq->head == NULL)
{
return -1;
}*/
assert(!QueueEmpty(pq));
//情况2
QueueNode* next = pq->head->next;//保存下一个结点
free(pq->head);//释放队头
pq->head = next;//next成为新的队头
//注意!!!!如果一直删,删最后一个时候 此时next为NULL的,如果不把tail也置空,就会造成野指针
if (pq->head == NULL)
{
pq->tail = NULL;
}
}
//取队头数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
//链表为空
/*if (pq->head == NULL)
{
return -1;
}*/
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);
//方法1:遍历统计
//方法2:定义结构体时添加一个size变量,入数据:size++ 出数据size -- 用size标志队列长度
//遍历统计
QueueNode* cur = pq->head;
int count = 0;
while (cur)
{
count++;
cur = cur->next;
}
return count;
}
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
/*if (pq -> head == NULL)
{
return true;
}
else
{
return false;
}*/
return pq->head == NULL;
}
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) {
//往不为空的队列中入数据
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
//出数据
int myStackPop(MyStack* obj)
{
//把有数据的队列的数据导入到空队列
//先假设某一个队列不为空,假设队列q1不为空,q2为空
Queue* noemptyQ = &obj->q1;
Queue* emptyQ = &obj->q2;
//如果q2不为空,说明假设反了
if(!QueueEmpty(&obj->q2))
{
emptyQ = &obj->q1;
noemptyQ = &obj->q2;
}
//把不空队列的数据导入到空队列,直到不空队列只剩一个元素
while(QueueSize(noemptyQ) > 1)
{
QueuePush(emptyQ,QueueFront(noemptyQ));
QueuePop(noemptyQ);
}
int top = QueueFront(noemptyQ);
QueuePop(noemptyQ);
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);
}
/**
* 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);
*/
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)