栈和队列经典试题

本文探讨了如何使用栈和队列实现高效的数据操作。包括如何在一个栈中保持最小值的O(1)时间复杂度,通过两个栈模拟队列,两个队列实现栈,验证出入栈顺序合法性,以及在一个数组中实现两个共享栈。每个问题都提供了详细的思路解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01.实现一个栈,要求实现Push、Pop、Min(返回最小值)的时间复杂度为O(1)
  • 思路:我们知道取栈顶元素的时间复杂度为O(1), 如果栈顶元素就是最小的就好了,所以我们每次入栈之前, 先与栈顶元素比较
  • 如果大于栈顶元素, 就把栈顶元素保存一份, 先入栈要入栈的元素, 再入栈栈顶元素
  • 如果小于栈顶元素就直接入栈两次这个元素
  • 同样, 出栈也要每次出两个元素
  • 例如:要入栈的是5, 当前栈顶元素是3, 那么先入栈5, 再入栈3, 就保证了栈顶的元素永远是最小的

//实现一个栈,要求实现Push、Pop、Min(返回最小值)的时间复杂度为O(1)
//方法一: 每次入栈之前和当前栈顶元素比较
//        如果入栈的元素小,就直接入栈两个此元素
//        如果栈顶元素小,就先入栈当前元素,再将栈顶元素入栈
//        这样每次入栈时都是入栈两个元素,并且保证栈顶元素永远是最小的
#include <stdio.h>
#include <stdlib.h>

#define DEFAULT_SZ 4

typedef char DataType;

typedef struct seqStack
{
    DataType* data;
    int size;//当前栈内元素的数量
    int capacity;//栈的容量
}seqStack;

//初始化栈
void seqStackInit(seqStack* stack)
{
    stack->data = (DataType*)malloc(sizeof(DataType) * DEFAULT_SZ);
    stack->size = 0;
    stack->capacity = DEFAULT_SZ;
}

//入栈 Push
void seqStackPush(seqStack* stack, DataType data)
{
    if(stack == NULL)
    {
        //非法输入
        return ;
    }
    if(stack->size == stack->capacity)
    {
        //栈满, 需要扩容
        DataType* ptr = (DataType*)realloc(stack->data, sizeof(DataType)*stack->capacity*2 + 1);
        stack->data = ptr;
    }
    //将入栈元素和栈顶元素比较
    if(data <= stack->data[stack->size-1] || stack->size == 0)
    {
        //入栈元素小于等于栈顶元素,就直接入栈两个此元素
        stack->data[stack->size] = data;
        ++stack->size;
        stack->data[stack->size] = data;
        ++stack->size;
    }
    else
    {
        //如果大于栈顶元素,就先入栈此元素,再入栈栈顶元素
        DataType min = stack->data[stack->size - 1];
        stack->data[stack->size] = data;
        ++stack->size;
        stack->data[stack->size] = min;
        ++stack->size;
    }
}

//出栈 Pop
void seqStackPop(seqStack* stack)
{
    if(stack == NULL)
    {
        //非法输入
        return ;
    }
    if(stack->size == 0)
    {
        //空栈
        return ;
    }
    //出栈也要每次都出两个元素,才能保证当前栈顶永远是最小值
    //free(&stack->data[stack->size-1]);
    --stack->size;
    //free(&stack->data[stack->size-1]);
    --stack->size;
}

//返回最小值 Min
DataType* seqStackMin(seqStack* stack)
{
    if(stack == NULL)
    {
        return NULL;
    }
    if(stack->size == 0)
    {
        return NULL;
    }
    //返回最小值就是获取栈顶元素就可以了
    return &(stack->data[stack->size - 1]);
}

//打印栈
void seqStackPrint(seqStack* stack, char* msg)
{
    printf("\n=====%s=====\n", msg);
    if(stack == NULL)
    {
        return ;
    }
    if(stack->size == 0)
    {
        return ;
    }
    for(int i=stack->size - 1; i>=0; i--)
    {
        printf("[%c]\n", stack->data[i]);
    }
    printf("\n");
}

int main()
{
    seqStack stack;
    seqStackInit(&stack);
    seqStackPush(&stack, 'a');
    seqStackPush(&stack, 'b');
    seqStackPush(&stack, 'c');
    seqStackPush(&stack, 'd');
    seqStackPrint(&stack, "入栈4次");

    DataType* min;
    min = seqStackMin(&stack);
    printf("min expect a, actual %c\n", *min);

    seqStackPop(&stack);
    seqStackPop(&stack);
    seqStackPrint(&stack, "出栈2次");

    min = seqStackMin(&stack);
    printf("min expect a, actual %c\n", *min);

    seqStackPop(&stack);
    seqStackPop(&stack);
    seqStackPrint(&stack, "再出栈2次");

    seqStackPop(&stack);
    seqStackPrint(&stack, "尝试对空栈出栈");

    printf("\n\n\n");
    printf("\n\n\n");
    printf("\n\n\n");
    printf("\n\n\n");
    return 0;
}

这里写图片描述


02.两个栈实现一个队列
  • 思路: 两个栈, 一个用来进(input), 一个用来出(output), 入队列之后想要出队列, 就要先把input里的元素出栈, 然后入栈到output里面, 这样刚才input的栈底元素就变成了栈顶元素, 就可以先出了, 这样就达到了队列的先进先出
  • 每次出完队列以后要把output里的元素出栈, 入栈回input里面, 等待下一次的入队列

//两个栈实现一个队列
//定义两个栈 一个stack栈 一个output栈
//人队列从stack入, 出队列先把stack栈的元素入栈到output栈, 再从output栈出
#include <stdio.h>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值