单调栈c语言实现

栈的常用操作

  1. 进栈 - push - 将元素放置到栈顶
  2. 退栈 - pop - 将栈顶元素弹出
  3. 栈顶 - top - 得到栈顶元素的值
  4. 是否空栈 - isEmpty - 判断栈内是否有元素

应用

  • 函数调用栈
  • 浏览器前进后退
  • 匹配括号
  • 单调栈用来寻找下一个更大(更小)元素

单调栈又是什么?

单调栈是一种特殊的栈。栈本来就是一种受限的数据结构了,单调栈在此基础上又受限了一次(受限++)。

单调栈要求栈中的元素是单调递减或者单调递减的。

是否严格递减或递减可以根据实际情况来。

这里我用 [a,b,c] 表示一个栈。 其中 左侧为栈底,右侧为栈顶。单调增还是单调减取决于出栈顺序。如果出栈的元素是单调增的,那就是单调递增栈,如果出栈的元素是单调减的,那就是单调递减栈。

比如:

  • [1,2,3,4] 就是一个单调递减栈(因为此时的出栈顺序是 4,3,2,1。下同,不再赘述)
  • [3,2,1] 就是一个单调递增栈
  • [1,3,2] 就不是一个合法的单调栈

那这个限制有什么用呢?这个限制(特性)能够解决什么用的问题呢?

适用场景

单调栈适合的题目是求解下一个大于 xxx或者下一个小于 xxx这种题目。所有当你有这种需求的时候,就应该想到单调栈。

那么为什么单调栈适合求解下一个大于 xxx或者下一个小于 xxx这种题目?原因很简单,我这里通过一个例子给大家讲解一下。

这里举的例子是单调递减栈

比如我们需要依次将数组 [1,3,4,5,2,9,6] 压入单调栈。

  1. 首先压入 1,此时的栈为:[1]
  2. 继续压入 3,此时的栈为:[1,3]
  3. 继续压入 4,此时的栈为:[1,3,4]
  4. 继续压入 5,此时的栈为:[1,3,4,5]
  5. 如果继续压入 2,此时的栈为:[1,3,4,5,2] 不满足单调递减栈的特性, 因此需要调整。如何调整?由于栈只有 pop 操作,因此我们只好不断 pop,直到满足单调递减为止。
  6. 上面其实我们并没有压入 2,而是先 pop,pop 到压入 2 依然可以保持单调递减再 压入 2,此时的栈为:[1,2]
  7. 继续压入 9,此时的栈为:[1,2,9]
  8. 如果继续压入 6,则不满足单调递减栈的特性, 我们故技重施,不断 pop,直到满足单调递减为止。此时的栈为:[1,2,6]

栈的实现

栈是较容易实现的抽象数据结构之一。我们可以选择数组或者链表来实现,它们各有特点,前者容量有限且固定,但操作简单,而后者容量理论上不受限,但是操作并不如数组方便,每次入栈要进行内存申请,出栈要释放内存,稍有不慎便造成内存泄露。本文对两种实现都做介绍。

数组实现栈

用数组实现栈是比较容易的。这个时候的栈其实更像是访问受限的数组,数组可以通过下标访问,查找,插入等,但是栈只能从栈顶,或者说数组的末尾进行操作。我们只需要一个指针记录栈顶即可。有人可能问了,既然这里栈是访问受限的数组,为什么不直接使用数组呢?所谓能力越大,责任越大,而你暴露的越多,风险也越大就是如此。

c语言实现

#include<stdio.h>

#define STACK_SIZE 64 /*栈大小*/
#define TOP_OF_STACK -1 /*栈顶位置*/
typedef int ElementType; /*栈元素类型*/

#define SUCCESS 0
#define FAILURE -1

/*定义栈结构*/
typedef struct StackInfo
{
    int topOfStack; /*记录栈顶位置*/
    ElementType stack[STACK_SIZE]; /*栈数组,也可以使用动态数组实现*/
}StackInfo_st;


/*函数声明*/
int stack_push(StackInfo_st *s,ElementType value);
int stack_pop(StackInfo_st *s,ElementType *value);
int stack_top(StackInfo_st *s,ElementType *value);
int stack_is_full(StackInfo_st *s);
int stack_is_empty(StackInfo_st *s);


/*入栈,0表示成,非0表示出错*/
int stack_push(StackInfo_st *s,ElementType value)
{
    if(stack_is_full(s))
        return FAILURE;
    /*先增加topOfStack,再赋值*/
    s->topOfStack++;
    s->stack[s->topOfStack] = value;
    return SUCCESS;
}

/*出栈*/
int stack_pop(StackInfo_st *s,ElementType *value)
{
    /*首先判断栈是否为空*/
    if(stack_is_empty(s))
        return FAILURE;
    *value = s->stack[s->topOfStack];
    s->topOfStack--;
    return SUCCESS;
}

/*访问栈顶元素*/
int stack_top(StackInfo_st *s,ElementType *value)
{
    /*首先判断栈是否为空*/
    if(stack_is_empty(s))
        return FAILURE;
    *value = s->stack[s->topOfStack];
    return SUCCESS;
}

/*判断栈是否已满,满返回1,未满返回0*/
int stack_is_full(StackInfo_st *s)
{
    return s->topOfStack == STACK_SIZE - 1;
}

/*判断栈是否为空,空返回1,非空返回0*/
int stack_is_empty(StackInfo_st *s)
{
    return s->topOfStack ==  - 1;
}
int main(void)
{
    
    /*创建栈*/
    StackInfo_st stack;
    stack.topOfStack = TOP_OF_STACK;
    
    /*如果栈为空,则压入元素1*/
    if(stack_is_empty(&stack))
    {
        printf("push value 1\n");
        stack_push(&stack,1);
    }
    
    /*访问栈顶元素*/
    int topVal;
    stack_top(&stack, &topVal);
    printf("top value %d\n",topVal);
    
    /*出栈*/
    int popVal;
    stack_pop(&stack, &popVal);
    printf("pop value %d\n",popVal);
    int i = 0;
    while(SUCCESS == stack_push(&stack,i))
    {
        i++;
    }
    printf("stack is full,topOfStack is %d\n",stack.topOfStack);
    
    return 0;
}

例题:每日温度

请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。
如果气温在这之后都不会升高,请在该位置用 0 来代替。

例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],
你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。

提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

通过次数175,107提交次数260,236

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/daily-temperatures
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

#include<string.h>

#define STACK_TOP_IDX -1

struct stack_st

{

    int stackTop;

    int stackData[30000];

};

int Top(struct stack_st *stackData, int *value)

{

    if (stackData->stackTop == STACK_TOP_IDX)

    {

        return 0;

    }

    *value = stackData->stackData[stackData->stackTop];

    return 1;

}

void pop(struct stack_st *stackData)

{

    if (stackData->stackTop == STACK_TOP_IDX)

    {

        return ;

    }

    stackData->stackTop--;

    return ;

}

void push(struct stack_st *stackData, int data)

{

    if (stackData->stackTop == 29999)

    {

        return ;

    }

    stackData->stackTop++;

    stackData->stackData[stackData->stackTop] = data;

    return ;

}

int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize){

    int ret = 0, mid = 0, i = 0;

    int *temp = (int *)calloc(temperaturesSize, sizeof(int));

    if (temperaturesSize <= 1)

    {

        *returnSize = 1;

        printf("0\n");

        temp[0] = 0;

        return temp;

    }

    struct stack_st myStack;

    memset(&myStack, 0, sizeof(struct stack_st));

    myStack.stackTop = STACK_TOP_IDX;

    push(&myStack, 0);

    for (i = 0; i < temperaturesSize - 1; i++)

    {       

        if (temperatures[i+1] <= temperatures[i])

        {

            push(&myStack, i+1);

        }

        else

        {

            while(1)

            {           

                if (!Top(&myStack, &mid))

                    break;

                if (temperatures[mid] < temperatures[i+1])

                {

                    temp[mid] = i+1;

                    pop(&myStack);

                }

                else

                {

                    break;

                }

            }

            push(&myStack, i+1);

        }       

    }

    for (i = 0; i < temperaturesSize ; i++)

    {

        temp[i] = temp[i] - i;

        if (temp[i] < 0)

            temp[i] = 0;

        if (i == temperaturesSize - 1)

            printf("%d\n", temp[i]);

        else

            printf("%d, ", temp[i]);

    }

    *returnSize = temperaturesSize;

    return temp;

}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单调栈是一种特殊的栈结构,它的主要应用是用于解决求某个元素的左边或右边第一个比它大或小的元素的问题。单调栈的特点是栈中的元素保持有序,即栈顶元素最小或最大。而发射站是一个具体的应用场景,我们可以利用单调栈来解决相关问题。 在一个发射站中,我们需要找到每个位置的第一个比它大的位置。我们可以使用单调栈实现这个功能。首先,我们将第一个元素的下标入栈。然后,依次遍历剩下的每个元素。对于每个元素,我们将它与栈顶元素进行比较。如果当前元素比栈顶元素大,说明找到了以栈顶元素为高度的发射站,我们可以更新它对应的输出结果,并弹出栈顶元素。直到当前元素小于或等于栈顶元素,我们将当前元素的下标入栈。这样,最后栈中剩下的元素对应的输出结果为-1,表示没有找到比它大的位置。 使用单调栈来解决发射站问题的时间复杂度为O(n),其中n为发射站的个数。这是因为每个元素最多入栈一次,出栈一次,所以遍历所有元素的时间复杂度为O(n)。而每个元素入栈和出栈的操作时间复杂度为O(1)。因此,总的时间复杂度为O(n)。 综上所述,利用单调栈结构可以高效地解决发射站问题。通过遍历发射站中的元素,可以找到每个位置的第一个比它大的位置。这种方法的时间复杂度为O(n),其中n为发射站的个数。因此,使用单调栈是一个有效的解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值