一.问题
实现一个栈,要求实现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, 如有纰漏,请斧正