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

题目描述:

定义栈的数据结构,要求添加一个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;       
       
} 




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值