目录
【1】括号匹配问题
思路分析
易错总结
Stack.h&Stack.c手撕栈
isValid括号匹配
【2】设计循环队列
今天接着栈&队列OJ题目。
【1】括号匹配问题
给定一个只包括
'('
,')'
,'{'
,'}'
,'['
,']'
的字符串s
,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
思路分析
- 左括号入栈
- 右括号与栈顶元素匹配(记得Pop)(顺序匹配)
- 考虑左/右括号多了(数量匹配)
易错总结
- 同一个域不能存在同名变量
- 类型的匹配度100%
- 字符串的比较用strcmp 字符比较==即可(字符的比较都是ASCII码)
- 出栈的性质:必须出了栈顶元素才能访问下一个元素
- 括号的匹配不是==
*s == ')'&& top != '(' || *s == '}'&& top != '{'|| *s == ']'&& top != '['
- return 之前都必须free ,不然会造成内存泄露的问题!!非常严重 先销毁再返回!!
Stack.h&Stack.c手撕栈
//stack.h
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef char STDatatype;
typedef struct Stack
{
STDatatype* a;
int top;
int capacity;
}ST;
void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst, STDatatype x);
void STPop(ST* pst);
STDatatype STTop(ST* pst);
bool STempty(ST* pst);
int STSize(ST* pst);
//stack.c
void STInit(ST* pst)
{
assert(pst);
pst->a = 0;
pst->top = 0;
pst->capacity = 0;
}
void Createcapacity(ST* pst)
{
if (pst->top == pst->capacity)
{
int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
STDatatype* tmp = (STDatatype*)realloc(pst->a, sizeof(ST) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
}
void STPush(ST* pst, STDatatype x)
{
assert(pst);
Createcapacity(pst);
pst->a[pst->top] = x;
pst->top++;
}
void STPop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
pst->top--;
}
STDatatype STTop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
return pst->a[pst->top-1];
}
bool STempty(ST* pst)
{
assert(pst);
return pst->top == 0;
}
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = 0;
pst->capacity = 0;
}
isValid括号匹配
bool isValid(char* s) {
ST stack;
STInit(&stack);
//遍历字符串
while(*s)
{
//左括号入栈
if(*s == '(' ||
*s == '{' ||
*s == '[' )
{
STPush(&stack,*s);
}
else//右括号
{
//数量匹配 左括号<右括号
if(STempty(&stack))
{
STDestroy(&stack);
return false;
}
//右括号取栈顶的元素比较
//记住要Pop
char top=STTop(&stack);
STPop(&stack);
//因为true 不是一次匹配成功 flase是依次成功
if( *s == ')'&& top != '(' ||
*s == '}'&& top != '{'||
*s == ']'&& top != '[' )
{
STDestroy(&stack);
return false;
}
}
s++;
}
//数量匹配,左括号>右括号
STDestroy(&stack);
return STempty(&stack);
}
【2】设计循环队列
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k)
: 构造器,设置队列长度为 k 。Front
: 从队首获取元素。如果队列为空,返回 -1 。Rear
: 获取队尾元素。如果队列为空,返回 -1 。enQueue(value)
: 向循环队列插入一个元素。如果成功插入则返回真。deQueue()
: 从循环队列中删除一个元素。如果成功删除则返回真。isEmpty()
: 检查循环队列是否为空。isFull()
: 检查循环队列是否已满
//用数组实现+多开辟一个空间不放元素
typedef struct {
int*a;
int front;
int back;//数组下标
int k;//循环队列的最多放置数据
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
int*tmp=(int*)malloc(sizeof(int)*(k+1));//多开辟一个空间
obj->a=tmp;
obj->front=0;
obj->back=0;//指向最后一个元素的下一个
obj->k=k;
return obj;
}
//判断循环队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front == obj->back;//==0
}
//判断是否为满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->back+1) % (obj->k+1) == obj->front;//back+1=front
//操作符优先级问题
}
//插入元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))//true 满了
{
return false;
}
obj->a[obj->back] = value;
obj->back++;
obj->back %= obj->k+1;//处理
//obj->front+1%=obj->k+1;//处理左边不能为计算表达式
return true;
}
//删除元素
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return false;
}
else
{
obj->front++;
obj->front%=obj->k+1;//处理
return true;
}
}
//获取首元素
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
else
return obj->a[obj->front];
}
//获取尾元素
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
else
//return obj->a[(obj->back-1+obj->k+1)%(obj->k+1)];
return obj->a[(obj->back+obj->k)%(obj->k+1)];
}
//释放空间
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
obj=NULL;
}
/**
* Your MyCircularQueue struct will be instantiated and called as such:
* MyCircularQueue* obj = myCircularQueueCreate(k);
* bool param_1 = myCircularQueueEnQueue(obj, value);
* bool param_2 = myCircularQueueDeQueue(obj);
* int param_3 = myCircularQueueFront(obj);
* int param_4 = myCircularQueueRear(obj);
* bool param_5 = myCircularQueueIsEmpty(obj);
* bool param_6 = myCircularQueueIsFull(obj);
* myCircularQueueFree(obj);
*/
这个是用数组实现【循环队列】&后面博文会详细讲解。
- 数组实现【循环队列】
- 单链表实现【循环队列】
- 双向链表实现【循环队列】
✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!之后可能到1月分才会频繁继续更新博文了,要去准备英语和西语的考试,大家要乖乖敲代码哦!