
🎬 博主名称 :键盘敲碎了雾霭
🔥 个人专栏 : 《C语言》《数据结构》
⛺️指尖敲代码,雾霭皆可破

文章目录
- 一、有效的括号
-
- [1.1 问题描述](#1.1 问题描述)
- [1.2 解题思想](#1.2 解题思想)
- [1.3 代码实现](#1.3 代码实现)
- 二、用队列实现栈
-
- [2.1 问题描述](#2.1 问题描述)
- [2.2 解题思想](#2.2 解题思想)
- [2.3 代码实现](#2.3 代码实现)
- 三、用栈实现队列
-
- [3.1 问题描述](#3.1 问题描述)
- [3.2 解题实现](#3.2 解题实现)
- [3.3 代码实现](#3.3 代码实现)
- 四、设计循环队列
-
- [4.1 问题描述](#4.1 问题描述)
- [4.2 解题实现](#4.2 解题实现)
- [4.3 代码实现](#4.3 代码实现)
一、有效的括号
1.1 问题描述
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号
原链接:20.有效的括号
1.2 解题思想
左括号用栈的结构装起来,右括号每次比较前从栈拿左括号(后进后出)
1.3 代码实现
c
typedef char Datatype;
typedef struct STack
{
Datatype*arr;
int size;
int capacity;
}ST;
void STInit(ST*pst)
{
assert(pst);
pst->arr=NULL;
pst->size=pst->capacity=0;
}
void STPush(ST*pst,Datatype x)
{
assert(pst);
if(pst->size==pst->capacity)
{
int newcapacity=pst->capacity==0?4:pst->capacity*2;
Datatype*ptr=(Datatype*)realloc(pst->arr,sizeof(Datatype)*newcapacity);
if(ptr==NULL)
{
perror("realloc");
return;
}
pst->arr=ptr;
pst->capacity=newcapacity;
}
pst->arr[pst->size++]=x;
}
void STPop(ST*pst)
{
assert(pst->size>0);
assert(pst);
pst->size--;
}
bool STEmpty(ST*pst)
{
return pst->size==0;
}
Datatype STTop(ST*pst)
{
assert(pst);
assert(!STEmpty(pst));
return pst->arr[pst->size-1];
}
int STSize(ST*pst)
{
assert(pst);
return pst->size;
}
void STDestroy(ST*pst)
{
assert(pst);
if(pst->arr)
{
free(pst->arr);
}
pst->size=pst->capacity=0;
}
bool isValid(char* s)
{
ST st;
STInit(&st);
while(*s)
{
if(*s=='{'||*s=='['||*s=='(')
{
STPush(&st,*s);
}
else
{
if(STEmpty(&st))
{
STDestroy(&st);
return false;
}
Datatype tmp =STTop(&st);
if((*s==']'&&tmp!='[')||(*s=='}'&&tmp!='{')||(*s==')'&&tmp!='('))
{
return false;
}
STPop(&st);
}
s++;
}
if(!STEmpty(&st))
{
STDestroy(&st);
return false;
}
return true;
}
二、用队列实现栈
2.1 问题描述
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
原链接:225.用队列实现栈
2.2 解题思想
找头元素时,把元素导入空队列,增元素时,添加到非空队列
2.3 代码实现
c
typedef int QDatatype;
typedef struct QueueNode
{
QDatatype val;
struct QueueNode*next;
}QNode;
typedef struct Queue
{
QNode*phead;
QNode*ptail;
int size;
}Queue;
void QInit(Queue*q)
{
assert(q);
q->phead=q->ptail=NULL;
q->size=0;
}
void QPush(Queue *q,QDatatype x)
{
assert(q);
QNode*newnode=(QNode*)malloc(sizeof(QNode));
if(newnode==NULL)
{
perror("malloc");
return;
}
newnode->next=NULL;
newnode->val=x;
if(q->phead==NULL)
{
q->phead=q->ptail=newnode;
}
else
{
q->ptail->next=newnode;
q->ptail=newnode;
}
q->size++;
}
void QPop(Queue *q)
{
assert(q);
assert(q->size>0);
if(q->phead->next==NULL)
{
free(q->phead);
q->phead=q->ptail=NULL;
}
else
{
QNode*next = q->phead->next;
free(q->phead);
q->phead=next;
}
q->size--;
}
int QTop(Queue*q)
{
assert(q);
assert(q->phead);
return q->phead->val;
}
int QBack(Queue*q)
{
assert(q);
assert(q->ptail);
return q->ptail->val;
}
bool QEmpty(Queue *q)
{
assert(q);
return q->size==0;
}
int QSize(Queue*q)
{
assert(q);
return q->size;
}
void QDestroy(Queue *q)
{
assert(q);
while(q->phead)
{
QNode*next =q->phead->next;
free(q->phead);
q->phead=next;
}
q->ptail=q->phead=NULL;
}
typedef struct
{
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate()
{
MyStack *pst=(MyStack*)malloc(sizeof(MyStack));
QInit(&pst->q1);
QInit(&pst->q2);
return pst;
}
void myStackPush(MyStack* obj, int x)
{
assert(obj);
if(!QEmpty(&obj->q1))
{
QPush(&obj->q1,x);
}
else
{
QPush(&obj->q2,x);
}
}
int myStackPop(MyStack* obj)
{
Queue *empty=&obj->q1;
Queue *nonempty=&obj->q2;
if(QEmpty(&obj->q2))
{
empty=&obj->q2;
nonempty=&obj->q1;
}
while(QSize(nonempty)>1)
{
QPush(empty,QTop(nonempty));
QPop(nonempty);
}
QDatatype ret =QTop(nonempty);
QPop(nonempty);
return ret;
}
int myStackTop(MyStack* obj)
{
if(!QEmpty(&obj->q1))
{
return QBack(&obj->q1);
}
else
{
return QBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj)
{
return (QEmpty(&obj->q1)&&QEmpty(&obj->q2));
}
void myStackFree(MyStack* obj)
{
QDestroy(&obj->q1);
QDestroy(&obj->q2);
free(obj);
}
三、用栈实现队列
3.1 问题描述
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
原题链接:225.用栈实现队列
3.2 解题实现
建立两个栈,第一个栈一个只入栈,当另一个栈不为空,将第一个栈栈倒置到另一个栈
3.3 代码实现
c
typedef int STDatatype;
typedef struct STack
{
STDatatype*arr;
int size;
int capacity;
}STack;
void STInit(STack*pst)
{
pst->arr=NULL;
pst->size=pst->capacity=0;
}
void STPush(STack*pst,STDatatype x)
{
if(pst->size==pst->capacity)
{
int newcapacity=pst->capacity==0?4:2*pst->capacity;
pst->arr=(STDatatype*)realloc(pst->arr,sizeof(STDatatype)*newcapacity);
pst->capacity=newcapacity;
}
pst->arr[pst->size++]=x;
}
void STPop(STack*pst)
{
pst->size--;
}
int STTop(STack*pst)
{
return pst->arr[pst->size-1];
}
bool STEmpty(STack*pst)
{
return pst->size==0;
}
void STDestroy(STack*pst)
{
if(pst->arr)
{
free(pst->arr);
}
pst->size=pst->capacity=0;
}
typedef struct
{
STack pushst;
STack popst;
} MyQueue;
int myQueuePeek(MyQueue* obj) ;
MyQueue* myQueueCreate()
{
MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
STInit(&obj->pushst);
STInit(&obj->popst);
return obj;
}
void myQueuePush(MyQueue* obj, int x)
{
STPush(&obj->pushst,x);
}
int myQueuePop(MyQueue* obj)
{
int ret = myQueuePeek(obj);
STPop(&obj->popst);
return ret;
}
int myQueuePeek(MyQueue* obj)
{
if(STEmpty(&obj->popst))
{
while(!STEmpty(&obj->pushst))
{
STPush(&obj->popst,STTop(&obj->pushst));
STPop(&obj->pushst);
}
}
int ret = STTop(&obj->popst);
return ret;
}
bool myQueueEmpty(MyQueue* obj)
{
return STEmpty(&obj->pushst)&&STEmpty(&obj->popst);
}
void myQueueFree(MyQueue* obj)
{
STDestroy(&obj->pushst);
STDestroy(&obj->popst);
free(obj);
}
四、设计循环队列
4.1 问题描述
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为"环形缓冲器"。
原题链接:622. 设计循环队列
4.2 解题实现
注意head和tail的边界情况(取模运算)
4.3 代码实现
c
typedef struct
{
int *arr;
int head;
int tail;
int k;
} MyCircularQueue;
bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
MyCircularQueue* myCircularQueueCreate(int k)
{
MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->arr=(int *)malloc(sizeof(int)*(k+1));
obj->head=obj->tail=0;
obj->k=k;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
if(myCircularQueueIsFull(obj))
{
return false;
}
obj->arr[obj->tail++]=value;
obj->tail%=(obj->k+1);
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
{
return false;
}
obj->head++;
obj->head%=obj->k+1;
return true;
}
int myCircularQueueFront(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->arr[obj->head];
}
int myCircularQueueRear(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->arr[((obj->tail-1)+(obj->k+1))%(obj->k+1)];
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->head==obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
if(((obj->tail+1)%(obj->k+1))==obj->head)
{
return true;
}
return false;
}
void myCircularQueueFree(MyCircularQueue* obj)
{
free(obj->arr);
free(obj);
}