题目描述:
定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。
要求函数min,push,pop的时间复杂度都是O(1).
解法1:另外设计一个最小栈做辅助结构,记录栈中的最小元素。元素栈中保存要入栈的元素。最小栈保存当前的最小元素。那么:
1.入栈时,先入元素栈,同时与最小栈顶元素比较,如果比栈顶元素小,则最小元素入最小栈,否则,栈顶元素入最小栈。
2.出栈时,栈一和栈二同时出栈。
则相应的算法如下。
注意的是:本算法中并没有对minStack做进一步的封装。因而这里的都是使用两个栈进行操作。如要符合题目的要求,应该在外层做进一步的封装。将minStack和元素栈作为最终栈的元素。类似
struct{
SelemType *top;
SelemType *base;
elemStack s;
minStack min;
int stackSize;
}
这种结构。
算法的优点是思路清晰。缺点是需要一个辅助栈。
#include
#include
#include
#include
//栈的初始最大容量
#define STACK_MAX_SIZE 100
//栈的容量增量
#define INCREAMENT 10
//状态函数
#define ERROR 0
#define OK 1
#define SOVERFLOW -1
#define YES 1
#define NO 0
typedef int Status,SElemType,ElemType;
typedef struct{
SElemType *base;
SElemType *top;
int stackSize;//当前已经分配的空间,不是指栈中元素个数。
}sqStack;
Status InitStack(sqStack &S){
//初始化栈空间,栈为空
S.base = (SElemType *)malloc(STACK_MAX_SIZE * sizeof(ElemType));
if(!S.base){
exit(SOVERFLOW);
}
S.top = S.base;
S.stackSize = STACK_MAX_SIZE;
return OK;
}
//如果栈不空,用e传出栈顶元素并返回OK。否则返回错误。
Status GetTop(sqStack S,SElemType &e){
if(S.top == S.base){
return ERROR;
}
e = *(S.top - 1);
return OK;
}
/*
* Push(S,e)向栈S中压入元素e。需要考虑的情况有:
* 1.栈已经满,需要增加空间。如果无法继续增加空间,则退出。
* 2.栈未满。先压入元素,然后修改栈顶指针。
**/
Status Push(sqStack &S,SElemType e){
if((S.top - S.base) >= S.stackSize){
S.base = (ElemType*)realloc(S.base,(S.stackSize + INCREAMENT) * sizeof(ElemType));
if(!S.base){
exit(SOVERFLOW);
}
S.top = S.base + S.stackSize;
S.stackSize += INCREAMENT;
}
//先压入元素,然后修改指针。弹出时相反
*S.top = e;
S.top ++;
return OK;
}
/*
* 弹出栈顶元素。需要注意的有:
* 1.栈不空。则先修改指针,然后弹出元素并传送给e。
* 2.栈为空时,返回错误。
*/
Status Pop(sqStack &S,ElemType &e){
if(S.top == S.base){
return ERROR;
}
//先修改指针,然后弹出元素。
S.top --;
e = *S.top;
return OK;
}
Status isEmpty(sqStack S){
if(S.top == S.base){
return YES;
}
return NO;
}
//以下几个函数是对入栈,出栈的封装。实际应用中,需要进一步对栈封装。这里没有封装。
//struct{
// elemStack s;
// minStack min;
//}
void PushIn(sqStack &S,sqStack &min,ElemType e){
ElemType tmp;
Push(S,e);
if(isEmpty(min)){
Push(min,e);
}else{
GetTop(min,tmp);
if(tmp >= e){
Push(min,e);
}else{
Push(min,tmp);
}
}
}
Status PopOut(sqStack &S,sqStack &min,ElemType &e){
if(!isEmpty(S) && !isEmpty(min)){
Pop(min,e);
Pop(S,e);
return OK;
}else{
return ERROR;
}
}
Status GetMin(sqStack S,sqStack min,ElemType &result){
if(!isEmpty(S) && !isEmpty(min)){
GetTop(min,result);
return OK;
}else{
return ERROR;
}
}
main(){
sqStack S,min;
InitStack(S);
InitStack(min);
int rands,rest;
printf("入栈:");
for(int i = 0;i < 100;i++){
rands = rand()%1000;
PushIn(S,min,rands);
GetMin(S,min,rest);
printf("%d -- min:%d \n",rands,rest);
}
printf("\n出栈:");
while(!isEmpty(S)){
PopOut(S,min,rest);
printf("%d ",rest);
}
system("pause");
return 0;
}
解法2:如果不设计另外一个辅助栈,那么可以修改栈的元素类型,增加一个min字段用于记录当前已经入栈的元素中的最小元素。
typedef int SelemType;
typedef int Status;
typedef struct{
minElement *base;
minElement *top;
int stackSize;//当前已经分配的空间,不是指栈中元素个数。
}minStack;
typedef struct{
SelemType data;
SelemType min;
}minElement;
操作的时候与一般的栈操作类似,不同的是push的时候需要同时push两个栈,且minStack中始终是当前最小元素在栈顶。
次思路的代码如下:
//代码功能,包含min函数的栈的实现。
#include
#include
#include
//栈的初始最大容量
#define STACK_MAX_SIZE 100
//栈的容量增量
#define INCREAMENT 10
//状态函数
#define ERROR 0
#define OK 1
#define SOVERFLOW -1
#define YES 1
#define NO 0
typedef int Status,ElemType;
typedef struct{
ElemType data;
ElemType min;
}minElement;
typedef struct{
minElement *base;
minElement *top;
int stackSize;//当前已经分配的空间,不是指栈中元素个数。
}minStack;
//typedef minElement SelemType;
Status InitStack(minStack &S){
//初始化栈空间,栈为空
S.base = (minElement *)malloc(STACK_MAX_SIZE * sizeof(minElement));
if(!S.base){
exit(SOVERFLOW);
}
S.top = S.base;
S.stackSize = STACK_MAX_SIZE;
return OK;
}
Status GetTop(minStack S,minElement &e){
if(S.top == S.base){
return ERROR;
}
e = *(S.top - 1);
return OK;
}
Status isEmpty(minStack S){
if(S.top == S.base){
return YES;
}
return NO;
}
Status Push(minStack &S,ElemType e){
if((S.top - S.base) >= S.stackSize){
S.base = (minElement*)realloc(S.base,(S.stackSize + INCREAMENT) * sizeof(minElement));
if(!S.base){
exit(SOVERFLOW);
}
S.top = S.base + S.stackSize;
S.stackSize += INCREAMENT;
}
//先压入元素,然后修改指针。弹出时相反.top指针始终在顶元素的下一个位置 。与pop时候的 操作刚好相反。
//TODO
minElement tmp,node;
node.data = e;
if(isEmpty(S)){
node.min = e;
}else{
GetTop(S,tmp);
node.min = tmp.min > e?e:tmp.min;
}
*(S.top) = node;
S.top++;
return OK;
}
Status Pop(minStack &S,minElement &e){
if(S.top == S.base){
return ERROR;
}
//先修改指针,然后弹出元素。top指针始终在顶元素的下一个位置
S.top --;
e = *S.top;
return OK;
}
Status getMin(minStack S,ElemType &e){
minElement tmp;
if(!isEmpty(S)){
GetTop(S,tmp);
e = tmp.min;
return OK;
}else{
return ERROR;
}
}
main(){
minStack S;
InitStack(S);
int rands,min;
printf("入栈:");
for(int i = 0;i < 100;i++){
rands = rand()%1000;
Push(S,rands);
getMin(S,min);
printf("%d -- min:%d \n",rands,min);
}
printf("\n出栈:");
minElement minE;
while(!isEmpty(S)){
Pop(S,minE);
printf("%d --- %d \n",minE.data,minE.min);
}
system("pause");
return 0;
}