引言
栈是一种线性的数据结构,栈最大的特点是“先入后出”,先存入的数据最后出去,后存入的数据先出去。
队列也是一种特殊的线性数据结构,队列与栈不同。队列的特点是“先入先出”。
正文
20. 有效的括号 - 力扣(LeetCode)https://leetcode.cn/problems/valid-parentheses/description/
第一题:有效括号
思路
这题的意思是给一个字符串字符串里面是括号当里面的扩号一 一对应时就返回true反之不匹配就返回false。这题需要通过用栈来解决问题,因为栈的特点是“先入后出”。将字符串中的数据插入到栈中,如果是左括号就插入到栈中,如果是右括号就判断和栈顶的左括号是否匹配,不匹配的话就返回false,匹配的话就出栈进行下一次比较直到字符串为空。
代码
bool isValid(char* s) {
//首先创建一个栈并初始化
Stack st;
StackInit(&st);
while(*s != '\0')
{
//如果是左括号就入栈
if(((*s)=='(')||((*s)=='{')||((*s)=='['))
{
StackPush(&st,*s);
}
else
{
//防止字符串种只有右括号
if(StackEmpty(&st))
{
//编程好习惯创建的内存要销毁防止内存泄漏
StackDestroy(&st);
return false;
}
//取出栈顶数据与下字符进行比较,取出之后需要删除以便下一次比较
int top = StackTop(&st);
StackPop(&st);
//这里需要注意的是如果判断匹配成功,没有什么意义因为要字符串中所有的括号都
//一 一对应的时才返回true,所以这里我们判断匹配失败情况。
if(((top == '(') && (*s != ')')) ||
((top == '{') && (*s != '}')) ||
((top == '[') && (*s != ']')))
{
StackDestroy(&st);
return false;
}
}
s++;
}
//防止栈中只有左括号的情况
bool ret = StackEmpty(&st);
StackDestroy(&st);
return ret;
}
第二题:用队列实现栈
225. 用队列实现栈 - 力扣(LeetCode)https://leetcode.cn/problems/implement-stack-using-queues/
思路
这题的意思是要我们用两个队列实现一个栈,并且实现栈的功能。
代码
typedef struct {
//创建两个队列
Queue q1;
Queue q2;
} MyStack;
//初始MyStack
MyStack* myStackCreate() {
//给MyStack结构体创建空间
MyStack *obj = (MyStack*)malloc(sizeof(MyStack));
//初始化两个队列
QueueInit(&(obj->q1));
QueueInit(&(obj->q2));
return obj;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&(obj->q1)))
{
QueuePush(&(obj->q1),x);
}
else
{
QueuePush(&(obj->q2),x);
}
}
int myStackPop(MyStack* obj) {
//假设法判空
Queue* empty=&(obj->q1);
Queue* noempty=&(obj->q2);
if(QueueEmpty(noempty))
{
empty = &(obj->q2);
noempty = &(obj->q1);
}
while(QueueSize(noempty)>1)
{
QueuePush(empty,QueueFront(noempty));
QueuePop(noempty);
}
int ret = QueueFront(noempty);
QueuePop(noempty);
return ret;
}
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) {
QueueDestroy(&(obj->q1));
QueueDestroy(&(obj->q2));
free(obj);
}
第三题:用栈实现队列
232. 用栈实现队列 - 力扣(LeetCode)https://leetcode.cn/problems/implement-queue-using-stacks/
思路
创建一个专用于入队列的栈push,再创建一个用于出队列的数据top。
代码
typedef struct {
ST push;
ST top;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue *obj = (MyQueue*)malloc(sizeof(MyQueue));
StackInit(&(obj->push));
StackInit(&(obj->top));
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
StackPush(&(obj->push),x);
}
int myQueuePeek(MyQueue* obj) {
//仅当push不为空top为空时才导数据
if(!StackEmpty(&(obj->push)))
{
if(StackEmpty(&(obj->top)))
{
while(!StackEmpty(&(obj->push)))
{
StackPush(&(obj->top),StackTop(&(obj->push)));
StackPop(&(obj->push));
}
}
}
return StackTop(&(obj->top));
}
int myQueuePop(MyQueue* obj) {
int ret = myQueuePeek(obj);
StackPop(&(obj->top));
return ret;
}
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&(obj->push)) && StackEmpty(&(obj->top));
}
void myQueueFree(MyQueue* obj) {
StackDestroy(&(obj->push));
StackDestroy(&(obj->top));
free(obj);
}
第四题:循环链表
622. 设计循环队列 - 力扣(LeetCode)https://leetcode.cn/problems/design-circular-queue/description/
思路
这哥题的意思是创建一个可以循环使用的队列,这队列的空间是确定的可以循环使用。然后实现这个循环队列的各种功能。实现这样一个循环队列的方法有链表法,数组法这里主要讲解数组法。
代码
typedef struct {
int *a;//指向数组的指针
int head;//首元素的下标
int tail;//最后一个元素的下一个元素下标
int k;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue*obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a = (int*)malloc(sizeof(int)*(k+1));
obj->head = 0;
obj->tail = 0;
obj->k = k;
return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->tail == obj->head;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return ((obj->tail)+1) % ((obj->k)+1) ==obj->head;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
//如果队列为满插入失败就返回false反之返回true
if(myCircularQueueIsFull(obj))
{
return false;
}
obj->a[obj->tail] = value;
++obj->tail;
//防止tail越界
(obj->tail) %= ((obj->k)+1);
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
//判断队列是否为空
if(myCircularQueueIsEmpty(obj))
{
return false;
}
//防止head越界
++obj->head;
(obj->head) %= ((obj->k)+1);
return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->a[obj->head];
}
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->a[((obj->tail) + (obj->k)) % ((obj->k)+1)];
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
obj->head = 0;
obj->tail = 0;
obj->k = 0;
free(obj);
}