LeetCode题目

  • 1、括号匹配问题
  • 2、用队列实现栈
  • 3、用栈实现队列
  • 4、设计循环队列

1、括号匹配问题

LeetCode链接: 【20. 有效的括号】

这道题就是经典的利用栈解决问题的例子;思路如下:
遍历一遍字符串,如果遇倒左括号就入栈,如果遇倒右括号取栈顶的元素进行匹配并出栈顶的元素,如果相匹配就继续,不匹配就返回false。
但是要注意这样只能检验出左右括号个数相等的情况下才可以,如果左右括号个数不相等呢?

  • 如果左括号多于右括号,并且遍历结束后它们都是匹配的,这种情况并不是完全匹配的,因为栈里还有元素剩余;所以遍历字符串后要加一个判断栈是否为空,只要栈为空了才是全部匹配完,没有剩余。 比如:“[[[[[((()))”
  • 如果右括号多余左括号,有可能导致栈是空的,栈里面没有元素可以取了,这种情况也是不匹配的;所以取栈顶元素的前面要加一个判断栈是否为空,如果栈为空说明右括号多余左括号,是不匹配的。比如:”((([[[ ]]]]]]]]]"

代码实现如下:

//C语言中没有栈,我们先实现一个栈
//构建栈如下:
typedef char STDataType;
struct Stack
{STDataType* a;int top;int capacity;
};
typedef struct Stack ST;//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//获取栈的元素个数
int StackSize(ST* ps);
//获取栈顶的元素
STDataType StackTop(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);void StackInit(ST* ps)
{ps->a = NULL;ps->capacity = 0;ps->top = 0;
}void StackDestroy(ST* ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;
}void StackPush(ST* ps,STDataType x)
{assert(ps);if (ps->capacity == ps->top){ps->capacity = ps->capacity > 0 ? ps->capacity * 2 : 2;STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * sizeof(STDataType));if (tmp == NULL){return;}else{ps->a = tmp;}}ps->a[ps->top] = x;ps->top++;
}void StackPop(ST* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}int StackSize(ST* ps)
{assert(ps);assert(ps->top > 0);return ps->top;
}STDataType StackTop(ST* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];
}bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}bool isValid(char * s){ST st;StackInit(&st);while(*s!='\0'){switch(*s){//压栈case '(':case '[':case '{':StackPush(&st,*s);s++;break;//取栈顶的数据进行匹配case ')':case ']':case '}'://出栈,从栈里面取做括号,栈里面的元素不能为空,//防止右括号过多,导致取到栈里面没有元素可以取,这也是不匹配if(StackEmpty(&st)){StackDestroy(&st);return false;}//取栈顶的数据和字符比较char top=StackTop(&st);StackPop(&st);if(top=='(' && *s==')' || top=='[' && *s==']' ||top=='{' && *s=='}'){s++;}else{StackDestroy(&st);return false;}}}//最后要判断栈是否为空//栈是空的说明才完全匹配,如果还要剩余说明没有是左括号多了,不匹配if(StackEmpty(&st)){StackDestroy(&st);return true;}else{StackDestroy(&st);return false;}}

2、用队列实现栈

LeetCode链接: 【225. 用队列实现栈】

思路: 这是要我们利用队列的性质去实现栈,队列的性质是先入先出,而栈的性质是后入先出;
所以我们利用两个队列来实现栈,一个为空队列,一个不为空队列;入栈:就往不为空的队列里面入,而 出栈就是: 只保留不为空的队列的最后一个元素,前面的元素都插入空队列中;然后再把最后一个元素出掉就是出栈了。


代码实现如下:

//C语言中没有队列,我们先构建一个队列的各种接口
//队列实现如下:
typedef int DataType;
typedef struct Node
{struct Node* next;DataType data;
}Node;typedef struct Queue
{Node* phead;Node* tail;
}Queue;//初始化队列
void QueueInit(Queue* pq);
//销毁队列
void QueueDestroy(Queue* pq);
//队列插数据
void QueuePush(Queue* pq,DataType x);
//队列出数据
void QueuePop(Queue* pq);
//取队尾数据
DataType QueueBack(Queue* pq);
//取队头数据
DataType QueueFront(Queue* pq);
//取队列中元素个数
int QueueSize(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->tail = NULL;
}void QueuePush(Queue* pq, DataType x)
{Node* tmp = (Node*)malloc(sizeof(Node));if (tmp == NULL){perror("malloc ");exit(-1);}tmp->data = x;tmp->next = NULL;if (pq->tail == NULL){pq->phead = tmp;pq->tail = tmp;}else{pq->tail->next = tmp;pq->tail = tmp;}
}void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);// 一个节点if (pq->phead->next == NULL){free(pq->phead);pq->phead = NULL;pq->tail = NULL;}//多个节点else{Node* tmp = pq->phead->next;free(pq->phead);pq->phead = tmp;}
}int QueueSize(Queue* pq)
{assert(pq);int count = 0;Node* cur = pq->phead;while (cur != NULL){cur = cur->next;count++;}return count;
}bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}DataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->data;
}DataType QueueBack(Queue* pq)
{assert(pq);assert(pq->phead);return pq->tail->data;
}void QueueDestroy(Queue* pq)
{assert(pq);Node* tmp = pq->phead;while (tmp != NULL){Node* next = tmp->next;free(tmp);tmp = next;}pq->phead = pq->tail = NULL;
}
//上面都是在实现队列的各种接口//下面是利用两个队列来实现栈
//用两给队列来实现栈,两个队列不断倒元素即可
typedef struct {Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() {MyStack* tmp=(MyStack*)malloc(sizeof(MyStack));if(tmp==NULL){perror("erron ");exit(-1);}QueueInit(&tmp->q1);QueueInit(&tmp->q2);return tmp;
}//往不为空的队列插数据,如果两个队列都为空,任意一个都行
void myStackPush(MyStack* obj, int x) {Queue* empty=&obj->q1;Queue* nonempty=&obj->q2;if(QueueEmpty(&obj->q2)){Queue* empty=&obj->q2;Queue* nonempty=&obj->q1;}QueuePush(nonempty,x);}//先把不为空的队列往空队列里面倒数据,倒到只剩下1个元素
//而这不为空的队列最后一个元素就是栈顶的元素,出掉即可
int myStackPop(MyStack* obj) {Queue* empty=&obj->q1;Queue* nonempty=&obj->q2;if(QueueEmpty(&obj->q2)){empty=&obj->q2;nonempty=&obj->q1;}while(QueueSize(nonempty)>1){QueuePush(empty,QueueFront(nonempty));QueuePop(nonempty);}//最后一个元素就是栈顶的元素//出掉即可,保证队列有一个为空队列int tmp=QueueBack(nonempty);QueuePop(nonempty);return tmp;}//直接取不为空的队列的尾元素即可
int myStackTop(MyStack* obj) {Queue* empty=&obj->q1;Queue* nonempty=&obj->q2;if(QueueEmpty(&obj->q2)){empty=&obj->q2;nonempty=&obj->q1;}return QueueBack(nonempty);
}bool myStackEmpty(MyStack* obj) {//两给队列都为空,栈才是空return QueueEmpty(&obj->q1)  && QueueEmpty(&obj->q2);
}void myStackFree(MyStack* obj) {QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj);
}

3、用栈实现队列

LeetCode链接: 【232. 用栈实现队列】

思路分析如下:

代码实现如下:

//C语言中没有栈,我们先实现一个栈
//构建栈如下:
typedef int STDataType;
struct Stack
{STDataType* a;int top;int capacity;
};
typedef struct Stack ST;//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//获取栈的元素个数
int StackSize(ST* ps);
//获取栈顶的元素
STDataType StackTop(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);void StackInit(ST* ps)
{ps->a = NULL;ps->capacity = 0;ps->top = 0;
}void StackDestroy(ST* ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;
}void StackPush(ST* ps,STDataType x)
{assert(ps);if (ps->capacity == ps->top){ps->capacity = ps->capacity > 0 ? ps->capacity * 2 : 2;STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * sizeof(STDataType));if (tmp == NULL){return;}else{ps->a = tmp;}}ps->a[ps->top] = x;ps->top++;
}void StackPop(ST* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}int StackSize(ST* ps)
{assert(ps);assert(ps->top > 0);return ps->top;
}STDataType StackTop(ST* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];
}bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}//两个栈,把不为空的栈往为空的栈里面倒过来就是队列了
//设计两个栈,一个用来入数据,一个用来出数据
//入数据就入pushst栈,出数据就出popst栈
typedef struct {ST Pushst; //入数据栈ST Popst;  //出数据栈
} MyQueue;MyQueue* myQueueCreate() {MyQueue* tmp=(MyQueue*)malloc(sizeof(MyQueue));if(tmp==NULL){perror("erron ");exit(-1);}StackInit(&tmp->Pushst);StackInit(&tmp->Popst);return tmp;
}void myQueuePush(MyQueue* obj, int x) {StackPush(&obj->Pushst,x);
}//要检验出数据的栈是否为空,没有数据了就从入数据的栈里面取
int myQueuePop(MyQueue* obj) {if(StackEmpty(&obj->Popst)){while(!StackEmpty(&obj->Pushst)){StackPush(&obj->Popst,StackTop(&obj->Pushst));StackPop(&obj->Pushst);}}int tmp=StackTop(&obj->Popst);StackPop(&obj->Popst);return tmp;
}//取队列的头元素,检验出数据的栈是否为空,没有数据了就从入数据的栈里面取
int myQueuePeek(MyQueue* obj) {if(StackEmpty(&obj->Popst)){while(!StackEmpty(&obj->Pushst)){StackPush(&obj->Popst,StackTop(&obj->Pushst));StackPop(&obj->Pushst);}}return StackTop(&obj->Popst);
}bool myQueueEmpty(MyQueue* obj) {return StackEmpty(&obj->Pushst) && StackEmpty(&obj->Popst);
}void myQueueFree(MyQueue* obj) {StackDestroy(&obj->Pushst);StackDestroy(&obj->Pushst);free(obj);
}

4、设计循环队列

LeetCode链接: 【622. 设计循环队列】

做这道题之前,我们先来了解什么是循环队列?它的解释如下:
循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列。
循环队列就是将队列存储空间的最后一个位置绕到第一个位置,形成逻辑上的环状空间,供队列循环使用。在循环队列结构中,当存储空间的最后一个位置已被使用而再要进入队运算时,只需要存储空间的第一个位置空闲,便可将元素加入到第一个位置,即将存储空间的第一个位置作为队尾。
循环队列可以更简单防止伪溢出的发生,但队列大小是固定的。

所以循环队列的结构搞清楚了,写起来就比较简单了,循环队列有两种实现方式,可以使用数组实现,也可以使用循环链表实现。下面分别来介绍。
链表实现如下:

//先创建一个结点类型
typedef struct Node
{struct Node* next;int data;
}Node;//创建一个循环队列类型结构体
//里面的头指针指向链表的头,尾指针指向链表的尾
typedef struct {Node* front;Node* tail;
} MyCircularQueue;//创建循环队列
MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* tmp=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));//构造一个环链表//要多构造一个结点,不然判断不了是否满了Node* head=(Node*)malloc(sizeof(Node));Node* a=head;Node* tail=head;while(k--){a=tail;tail=(Node*)malloc(sizeof(Node));a->next=tail;}tail->next=head;tmp->front=head;tmp->tail=head;return tmp;}//向循环队列插入一个元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(obj->tail->next==obj->front){return false;}obj->tail->data=value;obj->tail=obj->tail->next;return true;}//从循环队列中删除一个元素
bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(obj->front==obj->tail){return false;}obj->front=obj->front->next;return true;}//从队首获取元素
int myCircularQueueFront(MyCircularQueue* obj) {if(obj->front==obj->tail){return -1;}return obj->front->data;}//获取队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {if(obj->front==obj->tail){return -1;}//找队尾的前一个结点就是队尾数据Node* cur=obj->front;while(cur->next!=obj->tail){cur=cur->next;}return cur->data;}//检查循环队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front==obj->tail;}//检查循环队列是否已满。
bool myCircularQueueIsFull(MyCircularQueue* obj) {return obj->tail->next==obj->front;}//释放内存
void myCircularQueueFree(MyCircularQueue* obj) {Node* cur=obj->front;while(cur!=obj->tail){Node* next=cur->next;free(cur);cur=next;}free(cur);free(obj);
}

数组方式实现如下:

代码实现如下:

//在循环队列结构中设计一个指针指向一段连续的空间
typedef struct {int* a;int maxSize;int head;int tail;
} MyCircularQueue;bool myCircularQueueIsFull(MyCircularQueue* obj);//创建循环队列
MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* tmp=(MyCircularQueue*)malloc(sizeof(MyCircularQueue)); //要多开辟一个空间int* arr=(int*)malloc(sizeof(int)*(k+1));tmp->a=arr;tmp->maxSize=k+1;tmp->head=0;tmp->tail=0;return tmp;
}//向循环队列插入一个元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj)){return false;}obj->a[obj->tail]=value;obj->tail++;//把下标tail控制在数组中,不能越界if(obj->tail==obj->maxSize){obj->tail=0;}return true;
}//从循环队列中删除一个元素
bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(obj->head==obj->tail){return false;}obj->head++;if(obj->head==obj->maxSize){obj->head=0;}return true;
}//从队首获取元素
int myCircularQueueFront(MyCircularQueue* obj) {if(obj->head==obj->tail){return -1;}return obj->a[obj->head];}//获取队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {if(obj->head==obj->tail){return -1;}int i=0;if(obj->tail==0){i=obj->maxSize-1;}else{i=obj->tail-1;}return obj->a[i];
}//检查循环队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->head==obj->tail;
}//检查循环队列是否已满
bool myCircularQueueIsFull(MyCircularQueue* obj) {//方法1判断是否满了// return obj->head==(obj->tail+1)%obj->maxSize;//方法2判断是否满了int head=0;if(obj->head==0){head=obj->maxSize-1;}else{head=obj->head-1;}return head==obj->tail;}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);free(obj);
}

【LeetCode之栈和队列】:关于栈和队列经典的OJ题(用C语言实现,附图详解)相关推荐

  1. 【数据结构初阶】:栈和队列的实现(用C语言实现,附图详解和附源码)

    文章目录 栈的实现: 一.栈的概念和性质 二.栈的实现思路 三.栈的相关变量内存布局图 四.栈的初始化和销毁 五.栈的接口实现: 1.入栈 2.出栈 3.获取栈顶的数据 4.获取栈的元素个数 5.判断 ...

  2. 消息中间件系列(四):消息队列MQ的特点、选型、及应用场景详解

    前面集中谈了分布式缓存Redis系列: 高并发架构系列:分布式锁的由来.特点.及Redis分布式锁的实现详解 高并发架构系列:Redis并发竞争key的解决方案详解 高并发架构系列:Redis缓存和M ...

  3. LeetCode 225. Implement Stack using Queues--用队列实现栈--C++解法

    LeetCode 225. Implement Stack using Queues–用队列实现栈–C++解法 LeetCode题解专栏:LeetCode题解 我做的所有的LeetCode的题目都放在 ...

  4. Leetcode刷题 225题:用队列实现栈(基于Java和c++两种语言)

    ** Leetcode刷题 225题:用队列实现栈(基于Java和c++两种语言) ** 题目: 使用队列实现栈的下列操作: push(x) – 元素 x 入栈 pop() – 移除栈顶元素 top( ...

  5. LeetCode 232. 用栈实现队列(双栈法-队列)

    1. 题目 使用栈实现队列的下列操作: push(x) – 将一个元素放入队列的尾部. pop() – 从队列首部移除元素. peek() – 返回队列首部的元素. empty() – 返回队列是否为 ...

  6. LeetCode 239. 滑动窗口最大值(双端队列+单调栈)

    文章目录 1. 题目信息 2. 解题 2.1 暴力法 2.2 双端队列法 1. 题目信息 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内 ...

  7. python【力扣LeetCode算法题库】225-用队列实现栈

    用队列实现栈 使用队列实现栈的下列操作: push(x) – 元素 x 入栈 pop() – 移除栈顶元素 top() – 获取栈顶元素 empty() – 返回栈是否为空 注意: 你只能使用队列的基 ...

  8. leetcode 225 用队列实现栈(JS)

    使用队列实现栈的下列操作: push(x) -- 元素 x 入栈 pop() -- 移除栈顶元素 top() -- 获取栈顶元素 empty() -- 返回栈是否为空 注意: 你只能使用队列的基本操作 ...

  9. LeetCode(集合)队列和栈的相互实现 golang

    手写!!! 225. 用队列实现栈 使用队列实现栈的下列操作: push(x) – 元素 x 入栈 pop() – 移除栈顶元素 top() – 获取栈顶元素 empty() – 返回栈是否为空 注意 ...

最新文章

  1. AngularJS 、Backbone.js 和 Ember.js 的比较
  2. 新基建7大产业链约500家企业图谱!
  3. 在ue4制作中容易出现哪些问题_青年鸡在育成期容易出现的问题有哪些呢
  4. mysql的正则书写规则_MySql中正则表达式的使用方法描述
  5. 驱动级模拟驱动级模拟:直接读写键盘的硬件端口!
  6. 【bzoj4025】二分图 LCT
  7. mysql格式分隔符row_MySQLRow格式Binlog的解析(1)
  8. 63. Unique Paths II and 64. Minimum Path Sum
  9. 【蚁剑的安装与使用+例题实战】【CTF】webshell
  10. HDU 2277 Change the ball
  11. TensorFlow都有哪些模块?
  12. wpf中button的无边框实现
  13. 通俗易懂理解Attention机制
  14. 数据结构-第10周作业(二叉树的创建和遍历算法)
  15. 【游戏开发】UE4联机渲染swarm agent配置
  16. HttpClient的使用与连接资源释放
  17. 《秘密》BY东野圭吾
  18. 在 sysservers 中找不到服务器,在 sys.servers 中找不到服务器的解决办法,自己解决的...
  19. UniApp文件上传
  20. 【智能驾驶】最全、最强的无人驾驶技术学习路线

热门文章

  1. 曼尼托巴大学计算机科学硕士,曼尼托巴大学电气和计算机工程硕士解析
  2. 遥感领域多模态综述论文翻译
  3. tp计算机术语是什么意思,tp是什么意思呀?谁能把术语给我解释一下? – 手机爱问...
  4. win7 svn客户端 不显示绿色小队号等问题
  5. 欲望、外界、标签、天才、时间、经历、人生目标、后悔、和现实。转自特种兵—AK47
  6. Visual Studio 2010 项目属性配置
  7. android21是什么手机,三星S21成安卓新王者?详细对比发现,OPPO小米才是真厚道...
  8. JAVA电子竞技赛事管理系统计算机毕业设计Mybatis+系统+数据库+调试部署
  9. linux创建后门账户,Linux后门
  10. Oracle的基本练习:登陆、查看连接、管理登陆用户、修改进程数