最小栈问题------队列和栈面试题1

一.问题

实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值)的时间(即每次栈顶元素都是这个栈的最小值),而且时间复杂度为O(1)

有关于栈的详细讲解可以移步

顺序表实现的数据结构栈
链表实现的数据结构栈及相关函数

就这个问题,有如下两种思路

方法一

每次都入栈两个元素,第一个是本来入栈的元素,第二个是当前的最小值,对应的,每次出栈也是两个元素,当要返回最小值的时候,只要获取栈顶元素即可

方法二

再开辟一个栈MinStack,DataStack数据栈正常入栈元素,MinStack同步入栈DataStack当前最小元素
出栈时如果MinStack栈顶元素与DataStack当前栈顶元素相等,MinStack也出栈,如果不是,MinStack不出栈
返回最小值只需获取当前栈2栈顶元素即可

二.方法实现

seqstack.h以及它的 .c 实现移步

顺序表实现的数据结构栈

MinStack.h

#pragma once
// 上方有链接
#include "seqstack.h"

// 条件编译开关
#define PLAN 2

// 方法1
#if PLAN == 1
// 入栈
void MinStackPush(SeqStack* minstack, Datatype value);

// 出栈
void MinStackPop(SeqStack* minstack);

// 获取最小元素
int MinStackGetMinValue(SeqStack* minstack, Datatype* value);

// 方法2
#else 

typedef struct MinStack {
    // 数据栈
    SeqStack DataStack;
    // 最小数据栈
    SeqStack MinStack;
}MinStack;

// 入栈
void MinStackPush(MinStack* minstack, Datatype value);

// 出栈
void MinStackPop(MinStack* minstack);

// 获取最小元素
int MinStackGetMinValue(MinStack* minstack, Datatype* value);

#endif

MinStack.c

#include "minstack.h"


// 方法1
#if PLAN == 1
// 入栈
void MinStackPush(SeqStack* minstack, Datatype value) {
    // 非法输入
    if(minstack == NULL) {
        perror("Push");
        return;
    }
    // 取当前栈最小元素
    Datatype min;
    int ret = SeqStackTop(minstack, &min);
    // 空栈
    if(ret == 0) {
        // 入栈当前元素
        SeqStackPush(minstack, value);
        // 当前最小元素就是当前入栈元素
        SeqStackPush(minstack, value);
        return;
    } else {
        // 入栈元素比当前栈顶最小元素还小
        if(value <= min) {
            // 入栈当前元素
            SeqStackPush(minstack, value);
            // 入栈新的最小元素
            SeqStackPush(minstack, value);
        } else {
            // 入栈元素比当前最小元素大
            // 入栈当前元素
            SeqStackPush(minstack, value);
            // 将最小元素再入栈
            SeqStackPush(minstack, min);
        }
        return;
    }
}

// 出栈
void MinStackPop(SeqStack* minstack) {
    // 非法输入
    if(minstack == NULL) {
        perror("Pop");
        return;
    }
    // 空栈
    if(minstack->size == 0) {
        return;
    }
    // 连续出栈两个
    SeqStackPop(minstack);
    SeqStackPop(minstack);
}

// 获取最小元素
int MinStackGetMinValue(SeqStack* minstack, Datatype* value) {
    // 非法输入
    if(minstack==NULL || value==NULL) {
        perror("GetMinValue");
        return 0;
    }
    // 空栈
    if(minstack->size == 0) {
        return 0;
    }
    *value = minstack->data[minstack->size-1];
    return 1;
}

// 方法2
#else 
// 入栈
void MinStackPush(MinStack* minstack, Datatype value) {
    // 非法输入
    if(minstack == NULL) {
        perror("Push");
        return;
    }
    // 取当前栈最小元素
    Datatype min;
    int ret = SeqStackTop(&minstack->MinStack, &min);
    // 空栈
    if(ret == 0) {
        // 将当前元素入栈数据栈
        SeqStackPush(&minstack->DataStack, value);
        // 当前最小元就是当前元素,入栈最小数据栈
        SeqStackPush(&minstack->MinStack, value);
        return;
    } else {
        // 入栈元素比当前栈顶最小元素还小
        if(value <= min) {
            // 将当前元素入栈数据栈
            SeqStackPush(&minstack->DataStack, value);
            // 入栈最小数据进最小数据栈
            SeqStackPush(&minstack->MinStack, value);
        } else {
            // 入栈元素比当前最小元素大
            // 入栈当前元素
            SeqStackPush(&minstack->DataStack, value);
            // 将最小元素再入栈
            SeqStackPush(&minstack->MinStack, min);
        }
        return;
    }

}

// 出栈
void MinStackPop(MinStack* minstack) {
    // 非法输入
    if(minstack == NULL) {
        perror("Pop");
        return;
    }
    // 空栈
    if(minstack->DataStack.size == 0) {
        return;
    }
    // 两个栈同时出栈
    SeqStackPop(&minstack->DataStack);
    SeqStackPop(&minstack->MinStack);
}

// 获取最小元素
int MinStackGetMinValue(MinStack* minstack, Datatype* value) {
    // 非法输入
    if(minstack==NULL || value==NULL) {
        perror("GetMinValue");
        return 0;
    }
    // 空栈
    if(minstack->DataStack.size == 0) {
        return 0;
    }
    *value = minstack->MinStack.data[minstack->MinStack.size-1];
    return 1;
}

#endif





#if 1
/* *************************************************
 * ********************  test **********************
 * *************************************************/
#include <stdio.h>

#define FUNCTION() printf("=================== %s ==================\n", __FUNCTION__)

#if PLAN == 1

// 方法1打印栈
void print1(SeqStack stack, const char* msg) {
    printf("%s\n", msg);
    int i = 0;
    // 空栈
    if(stack.size == 0) {
        printf("空栈\n");
        return ;
    }
    printf("栈顶\n");
    for(i = stack.size-1; i >= 0; i--) {
        printf("%c\n", stack.data[i]);
    }
    return;
}

// 入栈测试
void TestPush() {
    FUNCTION();
    SeqStack stack;
    SeqStackInit(&stack);

    MinStackPush(&stack, '1');
    MinStackPush(&stack, '5');
    MinStackPush(&stack, '3');
    MinStackPush(&stack, '9');
    print1(stack, "入栈四次");
}

// 出栈测试
void TestPop() {
    FUNCTION();
    SeqStack stack;
    SeqStackInit(&stack);

    MinStackPush(&stack, '1');
    MinStackPush(&stack, '5');
    MinStackPush(&stack, '3');
    MinStackPush(&stack, '9');
    print1(stack, "栈初始化");

    MinStackPop(&stack);
    print1(stack, "出栈一次");

    MinStackPop(&stack);
    print1(stack, "出栈两次");

    MinStackPop(&stack);
    print1(stack, "出栈三次");

    MinStackPop(&stack);
    print1(stack, "出栈四次");

    MinStackPop(&stack);
    print1(stack, "空栈出栈");
}

// 返回最小元素测试
void TestMin() {
    FUNCTION();
    SeqStack stack;
    SeqStackInit(&stack);

    MinStackPush(&stack, '1');
    MinStackPush(&stack, '5');
    MinStackPush(&stack, '3');
    MinStackPush(&stack, '9');
    print1(stack, "栈初始化");

    Datatype value;
    int ret = MinStackGetMinValue(&stack, &value);
    printf("ret = %d, min value is %c\n", ret, value);
}

int main() {
    TestPush();
    TestPop();
    TestMin();
}

// 方法2
#else
// 方法2打印栈
void print2(MinStack stack, const char* msg) {
    printf("%s\n", msg);
    int i = 0;
    // 空栈
    if(stack.DataStack.size == 0) {
        printf("空栈\n");
        return ;
    }
    printf("数据栈栈顶\n");
    for(i = stack.DataStack.size-1; i >= 0; i--) {
        printf("%c\n", stack.DataStack.data[i]);
    }
    printf("最小数据栈栈顶\n");
    for(i = stack.MinStack.size-1; i >= 0; i--) {
        printf("%c\n", stack.MinStack.data[i]);
    }
    return;
}

// 入栈测试
void TestPush() {
    FUNCTION();
    //SeqStack stack;
    MinStack stack;
    SeqStackInit(&stack.DataStack);
    SeqStackInit(&stack.MinStack);

    MinStackPush(&stack, '1');
    MinStackPush(&stack, '5');
    MinStackPush(&stack, '3');
    MinStackPush(&stack, '9');
    print2(stack, "入栈四次");
}

// 出栈测试
void TestPop() {
    FUNCTION();
    //SeqStack stack;
    MinStack stack;
    SeqStackInit(&stack.DataStack);
    SeqStackInit(&stack.MinStack);

    MinStackPush(&stack, '1');
    MinStackPush(&stack, '5');
    MinStackPush(&stack, '3');
    MinStackPush(&stack, '9');
    print2(stack, "栈初始化");

    MinStackPop(&stack);
    print2(stack, "出栈一次");

    MinStackPop(&stack);
    print2(stack, "出栈两次");

    MinStackPop(&stack);
    print2(stack, "出栈三次");

    MinStackPop(&stack);
    print2(stack, "出栈四次");

    MinStackPop(&stack);
    print2(stack, "空栈出栈");
}

// 返回最小元素测试
void TestMin() {
    FUNCTION();
    //SeqStack stack;
    MinStack stack;
    SeqStackInit(&stack.DataStack);
    SeqStackInit(&stack.MinStack);

    MinStackPush(&stack, '1');
    MinStackPush(&stack, '5');
    MinStackPush(&stack, '3');
    MinStackPush(&stack, '9');
    print2(stack, "栈初始化");

    Datatype value;
    int ret = MinStackGetMinValue(&stack, &value);
    printf("ret = %d, min value is %c\n", ret, value);
}

int main() {
    TestPush();
    TestPop();
    TestMin();
}
#endif

本片代码由于是将两种方法写在一个 .h 与 .c 文件中,所以使用了条件编译,可以通过对 MinStack.h 中的宏 PLAN 的修改来控制编译的部分
代码实现平台为CentOS6.5, 如有纰漏,请斧正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值