【学习点滴-数据结构-栈&队列】设计一个min函数的栈

来源:互联网 发布:新手淘宝客 编辑:程序博客网 时间:2024/05/01 18:30

题目描述:

定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。

要求函数min,push,pop的时间复杂度都是O(1).


解法1:另外设计一个最小栈做辅助结构,记录栈中的最小元素。元素栈中保存要入栈的元素。最小栈保存当前的最小元素。那么:

       1.入栈时,先入元素栈,同时与最小栈顶元素比较,如果比栈顶元素小,则最小元素入最小栈,否则,栈顶元素入最小栈。

       2.出栈时,栈一和栈二同时出栈。

则相应的算法如下。

注意的是:本算法中并没有对minStack做进一步的封装。因而这里的都是使用两个栈进行操作。如要符合题目的要求,应该在外层做进一步的封装。将minStack和元素栈作为最终栈的元素。类似

struct{

    SelemType *top;

    SelemType *base; 
    elemStack s;
    minStack min;

    int stackSize;                                                                         
}
这种结构。

算法的优点是思路清晰。缺点是需要一个辅助栈。

 

#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <assert.h>//栈的初始最大容量 #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 <stdio.h>#include <stdlib.h>#include <malloc.h>//栈的初始最大容量 #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;              } 




原创粉丝点击