栈和队列oj问题详解

引言

  栈是一种线性的数据结构,栈最大的特点是“先入后出”,先存入的数据最后出去,后存入的数据先出去。

  队列也是一种特殊的线性数据结构,队列与栈不同。队列的特点是“先入先出”。

正文

20. 有效的括号 - 力扣(LeetCode)icon-default.png?t=N7T8https://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)icon-default.png?t=N7T8https://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)icon-default.png?t=N7T8https://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)icon-default.png?t=N7T8https://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);
}

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程菜鸟99号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值