目录
1.有效的括号
题目链接:
20. 有效的括号 - 力扣(LeetCode)
https://leetcode.cn/problems/valid-parentheses/description/题目描述:
给定一个只包括
'(',')','{','}','[',']'的字符串s,判断字符串是否有效。有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
思路:用栈来解决
//定义栈的结构
typedef char STDataType;
typedef struct stack {
STDataType* arr;
int top;
int capacity;
}stack;
//初始化
void STInit(stack* ps)
{
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
//销毁栈
void STDestroy(stack* ps)
{
if (ps->arr != NULL)
{
free(ps->arr);
}
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
//入栈
void STPush(stack* ps, STDataType x)
{
assert(ps);
//判断空间是否足够
if (ps->capacity == ps->top)
{
int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
STDataType* temp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
if (temp == NULL)
{
perror("realloc");
exit(1);
}
ps->arr = temp;
ps->capacity = newCapacity;
}
//空间足够
ps->arr[ps->top++] = x;
}
//判断栈是否为空
bool STEmpty(stack* ps)
{
assert(ps);
return ps->top == 0;
}
//出栈
void STPop(stack* ps)
{
assert(!STEmpty(ps));
ps->top--;
}
//取栈顶数据
STDataType STTop(stack* ps)
{
assert(!STEmpty(ps));
return ps->arr[ps->top - 1];
}
//获取栈中有效元素个数
int STSize(stack* ps)
{
assert(ps);
return ps->top;
}
bool isValid(char* s) {
//借助栈来实现
stack st;
STInit(&st);
char* pi=s;
while(*pi!='\0')
{
if(*pi=='('||*pi=='['||*pi=='{')
{
STPush(&st,*pi);
}
else{
if(STSize(&st)==0)
{
return false;
}
char top=STTop(&st);
if( (top=='('&&*pi==')') || (top=='['&&*pi==']') || (top=='{'&&*pi=='}') )
{
STPop(&st);
}
else{
STDestroy(&st);
return false;
}
}
pi++;
}
bool ret=STEmpty(&st)?true:false;
STDestroy(&st);
return ret;
}
2.用队列实现栈
题目链接:
225. 用队列实现栈 - 力扣(LeetCode)
https://leetcode.cn/problems/implement-stack-using-queues/description/题目描述:
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(
push、top、pop和empty)。实现
MyStack类:
void push(int x)将元素 x 压入栈顶。
int pop()移除并返回栈顶元素。
int top()返回栈顶元素。
boolean empty()如果栈是空的,返回true;否则,返回false。
思路:用空队列接收非空队列得前top-1个元素,再让最后一个元素出队列即可。

//定义队列结构
typedef struct QueueNode {
int data;
struct QueueNode* next;
} QueueNode;
typedef struct Queue {
QueueNode* phead;
QueueNode* ptail;
} Queue;
//队列有效元素个数
int QueueSize(Queue* pq)
{
assert(pq);
int size = 0;
QueueNode* pcur = pq->phead;
while (pcur!=NULL)
{
size++;
pcur = pcur->next;
}
return size;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* pst=(MyStack*)malloc(sizeof(MyStack));
//初始化栈
pst->q1.phead=pst->q1.ptail=NULL;
pst->q2.phead=pst->q2.ptail=NULL;
return pst;
}
void myStackPush(MyStack* obj, int x) {
QueueNode* newnode=(QueueNode*)malloc(sizeof(QueueNode));
newnode->data=x;
newnode->next=NULL;
//往不为空的队列里插入数据
if(obj->q1.phead!=NULL)
{
obj->q1.ptail->next=newnode;
obj->q1.ptail=obj->q1.ptail->next;
}
else if(obj->q2.phead!=NULL)
{
obj->q2.ptail->next=newnode;
obj->q2.ptail=obj->q2.ptail->next;
}
else {
obj->q1.phead = obj->q1.ptail = newnode;
}
}
int myStackPop(MyStack* obj) {
//找不为空队列
Queue* emp=&obj->q1;
Queue* noneEmp=&obj->q2;
if(obj->q2.phead==NULL)
{
emp=&obj->q2;
noneEmp=&obj->q1;
}
//不为空的队列前size-1个数据插入空队列中
while(QueueSize(noneEmp)>1)
{
QueueNode* newnode=(QueueNode*)malloc(sizeof(QueueNode));
newnode->data=noneEmp->phead->data;
newnode->next=NULL;
if (emp->phead == NULL)
{
emp->phead = emp->ptail = newnode;
}
else {
emp->ptail->next=newnode;
emp->ptail=emp->ptail->next;
}
//出队头
if (noneEmp->phead == noneEmp->ptail)
{
free(noneEmp->phead);
noneEmp->phead = noneEmp->ptail = NULL;
}
else {
QueueNode* next = noneEmp->phead->next;
free(noneEmp->phead);
noneEmp->phead = next;
}
}
int top=noneEmp->phead->data;
free(noneEmp->phead);
noneEmp->phead = noneEmp->ptail = NULL;
return top;
}
int myStackTop(MyStack* obj) {
//找不为空队列
Queue* emp=&obj->q1;
Queue* noneEmp=&obj->q2;
if(obj->q2.phead==NULL)
{
emp=&obj->q2;
noneEmp=&obj->q1;
}
//返回不为空队列的队尾
return noneEmp->ptail->data;
}
bool myStackEmpty(MyStack* obj) {
return obj->q1.phead==NULL&&obj->q2.phead==NULL;
}
void myStackFree(MyStack* obj) {
QueueNode* pcur1 = obj->q1.phead;
while (pcur1)
{
QueueNode* next = pcur1->next;
free(pcur1);
pcur1 = next;
}
obj->q1.phead = obj->q1.ptail = NULL;
QueueNode* pcur2 = obj->q2.phead;
while (pcur2)
{
QueueNode* next = pcur2->next;
free(pcur2);
pcur2 = next;
}
obj->q2.phead = obj->q2.ptail = NULL;
free(obj);
obj=NULL;
}
/**
* 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);
*/
这里写的有些麻烦,也可以直接套用之前写的队列的代码,必要的地步直接用之前的队列代码里定义的函数即可。
3.用栈实现队列
题目链接:
232. 用栈实现队列 - 力扣(LeetCode)
https://leetcode.cn/problems/implement-queue-using-stacks/description/题目描述:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
push、pop、peek、empty):实现
MyQueue类:
void push(int x)将元素 x 推到队列的末尾
int pop()从队列的开头移除并返回元素
int peek()返回队列开头的元素
boolean empty()如果队列为空,返回true;否则,返回false
思路:两个栈:pushST用来入队,popST用来出队

//定义栈的结构
typedef int STDataType;
typedef struct stack {
STDataType* arr;
int top;
int capacity;
}stack;
//初始化
void STInit(stack* ps)
{
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
//销毁栈
void STDestroy(stack* ps)
{
if (ps->arr != NULL)
{
free(ps->arr);
}
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
//入栈
void STPush(stack* ps, STDataType x)
{
assert(ps);
//判断空间是否足够
if (ps->capacity == ps->top)
{
int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
STDataType* temp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
if (temp == NULL)
{
perror("realloc");
exit(1);
}
ps->arr = temp;
ps->capacity = newCapacity;
}
//空间足够
ps->arr[ps->top++] = x;
}
//判断栈是否为空
bool STEmpty(stack* ps)
{
assert(ps);
return ps->top == 0;
}
//出栈
void STPop(stack* ps)
{
assert(!STEmpty(ps));
ps->top--;
}
//取栈顶数据
STDataType STTop(stack* ps)
{
assert(!STEmpty(ps));
return ps->arr[ps->top - 1];
}
//获取栈中有效元素个数
int STSize(stack* ps)
{
assert(ps);
return ps->top;
}
typedef struct {
stack pushST;
stack popST;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* pq=(MyQueue*)malloc(sizeof(MyQueue));
STInit(&pq->pushST);
STInit(&pq->popST);
return pq;
}
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->pushST,x);
}
int myQueuePop(MyQueue* obj) {
//从popST里面出数据
if(STEmpty(&obj->popST))
{
while(!STEmpty(&obj->pushST))
{
STPush(&obj->popST,STTop(&obj->pushST));
STPop(&obj->pushST);
}
}
int top=STTop(&obj->popST);
STPop(&obj->popST);
return top;
}
int myQueuePeek(MyQueue* obj) {
if(STEmpty(&obj->popST))
{
while(!STEmpty(&obj->pushST))
{
STPush(&obj->popST,STTop(&obj->pushST));
STPop(&obj->pushST);
}
}
int top=STTop(&obj->popST);
return top;
}
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->pushST)&&STEmpty(&obj->popST);
}
void myQueueFree(MyQueue* obj) {
STDestroy(&obj->pushST);
STDestroy(&obj->popST);
free(obj);
obj=NULL;
}
/**
* Your MyQueue struct will be instantiated and called as such:
* MyQueue* obj = myQueueCreate();
* myQueuePush(obj, x);
* int param_2 = myQueuePop(obj);
* int param_3 = myQueuePeek(obj);
* bool param_4 = myQueueEmpty(obj);
* myQueueFree(obj);
*/
4.设计循环队列
这里先介绍一下循环队列:
实际中还有⼀种特殊的队列叫循环队列,环形队列首尾相连成环,环形队列可以使用数组实现,也可以使用循环链表实现。但是考虑到使用的空间大小,还是推荐使用数组来实现循环队列。

用数组来实现,所以队列满了的情况就是 (rear+1) % (k + 1) = front 。
队列为空的情况就是 rear = front 。
题目链接:
622. 设计循环队列 - 力扣(LeetCode)
https://leetcode.cn/problems/design-circular-queue/description/题目描述:
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
思路:
typedef struct {
int* arr;
int front;
int rear;
int capacity;
} MyCircularQueue;
//初始化
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* pq=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
//给arr申请k+1个空间
pq->arr=(int*)malloc(sizeof(int)*(k+1));
pq->front=pq->rear=0;
pq->capacity=k;
return pq;
}
//向循环队列插入一个元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
//队列满了
if((obj->rear+1)%(obj->capacity+1)==obj->front)
{
return false;
}
obj->arr[obj->rear++]=value;
obj->rear=(obj->rear)%(obj->capacity+1);
return true;
}
//从循环队列中删除一个元素
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
//先检查队列是否为空
if(obj->front==obj->rear)
{
return false;
}
obj->front++;
obj->front=(obj->front)%(obj->capacity+1);
return true;
}
// /从队首获取元素
int myCircularQueueFront(MyCircularQueue* obj) {
if(obj->front==obj->rear)
{
return -1;
}
return obj->arr[obj->front];
}
//获取队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {
if(obj->front==obj->rear)
{
return -1;
}
int prev=obj->rear-1;
if(obj->rear==0)
{
prev=obj->capacity;
}
return obj->arr[prev];
}
//检查循环队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front==obj->rear;
}
//检查循环队列是否已满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->rear+1)%(obj->capacity+1)==obj->front;
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->arr);
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);
*/
2888

被折叠的 条评论
为什么被折叠?



