由栈的一些基本操作,很容易使出栈和入栈的时间复杂度为O(1),但是由于入栈数据元素顺序不一定是有序的,故不能直接实现返回最小值的时间复杂度为O(1)。下面提供两种方法:
(一)设置一个特殊的数据结构类型,包括两个栈_data栈和_mindata栈,_data栈和原来的栈操作相同,存储所有的数据,_mindata栈用来存储最小值。
typedef struct Minstack
{
Stack _data;
Stack _mindata;
}Minstack;
实例分析:假如入栈元素顺序为1,2,3,1。
1.1 入栈
入栈代码为:
//入栈 第一个元素入两个栈,后面的元素一定会入_data栈,如果data<=_mindata栈的栈顶元素,
//则入_mindata栈;否则不入_mindata栈。
void MinPush(Minstack *ms, SDataType data)
{
StackPush(&ms->_data, data);
//第一个元素入_mindata栈
if (Isempty(ms->_mindata))
{
StackPush(&ms->_mindata, data);
}
else
{
if (data <= TopStack(ms->_mindata))
{
StackPop(&ms->_mindata);
StackPush(&ms->_mindata, data);
}
}
}
出入栈的一些操作请戳上篇博客:https://blog.csdn.net/smell201611010513/article/details/82951212
1.2 出栈
_data栈一定会执行出栈操作,但是如果_data栈的栈顶元素和_mindata栈的栈顶元素相同,则_mindata栈也要执行出栈顺序,否则_mindata栈不作任何处理。出栈代码为:
void MinPop(Minstack *ms)
{
assert(ms->_data.top != 0);
if (TopStack(ms->_data) ==TopStack( ms->_mindata))
{
StackPop(&ms->_data);
StackPop(&ms->_mindata);
return;
}
StackPop(&ms->_data);
}
1.3 返回最小值
很明显,_mindata栈存储的就是栈内元素的最小值。代码为
SDataType Findmin(Minstack *ms)
{
return TopStack(ms->_mindata);
}
除栈的一些基本操作外,本题中的完整代码为
#pragma once
#include"Stack.h"
#include<assert.h>
//(一)设置两个栈,一个栈和普通的栈相同,一个栈存储入栈元素中最小的元素。
typedef struct Minstack
{
Stack _data;
Stack _mindata;
int top;
}Minstack;
//初始化
void MinInit(Minstack *ms)
{
InitStack(&(ms->_data));
InitStack(&(ms->_mindata));
}
//销毁
void MinDestroy(Minstack *ms)
{
StackDestroy(&ms->_data);
StackDestroy(&ms->_mindata);
}
//打印
void MinPrint(Minstack *ms)
{
PrintS(ms->_data);
PrintS(ms->_mindata);
}
//入栈 第一个元素入两个栈,后面的元素一定会入_data栈,如果data<=_mindata栈的栈顶元素,则入_mindata栈。
void MinPush(Minstack *ms, SDataType data)
{
StackPush(&ms->_data, data);
//第一个元素入_mindata栈
if (Isempty(ms->_mindata))
{
StackPush(&ms->_mindata, data);
}
else
{
if (data <= TopStack(ms->_mindata))
{
StackPop(&ms->_mindata);
StackPush(&ms->_mindata, data);
}
}
}
//出栈 _data栈一定会出栈,比较_data栈的栈顶元素和_mindata栈的栈顶元素,如果前者和后者相等,则_mindata栈也出栈。
void MinPop(Minstack *ms)
{
assert(ms->_data.top != 0);
if (TopStack(ms->_data) ==TopStack( ms->_mindata))
{
StackPop(&ms->_data);
StackPop(&ms->_mindata);
return;
}
StackPop(&ms->_data);
}
//找最小值
SDataType Findmin(Minstack *ms)
{
return TopStack(ms->_mindata);
}
void test3()
{
Minstack ms;
MinInit(&ms);
MinPush(&ms, 1);
MinPush(&ms, 2);
MinPush(&ms, 0);
MinPush(&ms, 3);
MinPrint(&ms);
MinPop(&ms);
MinPrint(&ms);
printf("%d\n", Findmin(&ms));
MinDestroy(&ms);
}
头文件“Stack.h”的具体操作代码请戳上篇博客:https://blog.csdn.net/smell201611010513/article/details/82951212
(二)设置一个类似于栈的特殊数据结构类型,包含array和top,其中array中的每个元素是一个包括两个数据元素的结构体。
其数据结构类型为:
#define Min2_size 100
typedef struct Elementenum
{
SDataType data;
SDataType min;
}Elementenum;
typedef struct Minstack2
{
Elementenum array[Min2_size];
int top;
}Minstack2;
2.1 入栈
假设入栈顺序为1,2,3,1,0.
对于ms2指向的栈,data入栈步骤为:
(1)首先判断ms2指向的栈是否为空,如果为空,将ms2指向的数组的data和min均赋值为data.然后ms2.top加1.
(2)如果不为空,那么data赋值给ms2->array[ms2->top].data,比较data和ms2->array[ms2->top-1].min,如果前者小,则把data赋值给ms2->array[ms2->top].min,否则把ms2->array[ms2->top-1].min赋给ms2->array[ms2->top].min。
(3)将ms2->top加1.
代码为
void Min2Push(Minstack2 *ms2, SDataType data)
{
if (Isempty2(ms2))
{
ms2->array[ms2->top].data = data;
ms2->array[ms2->top].min = data;
ms2->top++;
return;
}
if (ms2->array[ms2->top - 1].min < data)
{
ms2->array[ms2->top].min = ms2->array[ms2->top - 1].min;
ms2->array[ms2->top].data = data;
ms2->top++;
return;
}
ms2->array[ms2->top].min = data;
ms2->array[ms2->top].data = data;
ms2->top++;
}
2.2 出栈
出栈的操作和一般的栈相同。代码为
void Min2Pop(Minstack2 *ms2)
{
ms2->top--;
}
2.3 返回最小值
SDataType Min2min(Minstack2 *ms2)
{
return ms2->array[ms2->top - 1].min;
}
不过不要忘记对栈进行初始化哦,完整的代码为
#define Min2_size 100
typedef struct Elementenum
{
SDataType data;
SDataType min;
}Elementenum;
typedef struct Minstack2
{
Elementenum array[Min2_size];
int top;
}Minstack2;
//初始化
void Min2Init(Minstack2 *ms2)
{
ms2->top = 0;
}
//销毁
void Min2Destroy(Minstack2 *ms2)
{
ms2->top = 0;
}
//判空 空栈,返回1;非空,返回0.
int Isempty2(Minstack2 *ms2)
{
if (ms2->top == 0)
{
return 1;
}
return 0;
}
//打印
void Print2(Minstack2 *ms2)
{
if (ms2->top == 0)
{
printf("空栈\n");
return;
}
for (int i = 0; i < ms2->top;i++)
{
printf("%d ", ms2->array[i].data);
}
printf("\n%d\n", ms2->array[ms2->top - 1].min);
}
//入栈
void Min2Push(Minstack2 *ms2, SDataType data)
{
if (Isempty2(ms2))
{
ms2->array[ms2->top].data = data;
ms2->array[ms2->top].min = data;
ms2->top++;
return;
}
if (ms2->array[ms2->top - 1].min < data)
{
ms2->array[ms2->top].min = ms2->array[ms2->top - 1].min;
ms2->array[ms2->top].data = data;
ms2->top++;
return;
}
ms2->array[ms2->top].min = data;
ms2->array[ms2->top].data = data;
ms2->top++;
}
//出栈
void Min2Pop(Minstack2 *ms2)
{
ms2->top--;
}
//找最小元素
SDataType Min2min(Minstack2 *ms2)
{
return ms2->array[ms2->top - 1].min;
}
void test4()
{
Minstack2 ms2;
Min2Init(&ms2);
Min2Push(&ms2, 1);
Min2Push(&ms2, 3);
Min2Push(&ms2,5);
Min2Push(&ms2, 0);
Print2(&ms2);
Min2Pop(&ms2);
Print2(&ms2);
printf("%d\n", Min2min(&ms2));
Min2Destroy(&ms2);
}