【学习点滴-数据结构-栈&队列】 颠倒一个栈。

题目描述:对于一个非空栈,请设计一个算法颠倒栈中的元素。


首先我们设计的栈的实现代码是:

/*
 * 问题描述:栈实现的基本代码。
 * @author : xiaoq-ohmygirl
 * @time   : 2012-07-03 
 **/ 

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.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;   
} 



有了这个实现之后,栈的颠倒操作便有了基础。

思路1,也就是最简单的想法,基于栈的后入先出的性质。可以设计另一个辅助栈(栈2),每次栈1pop一个元素,栈2中push相应的元素。

算法如下:


sqStack reverseStack(sqStack S){
     sqStack help;
     InitStack(help); 
     SElemType node; 
     while(!isEmpty(S)){
          Pop(S,node);   
          Push(help,node);   
     }
     return help;       
} 

main(){
     sqStack S;
     sqStack tmp; 
     InitStack(S);
     InitStack(tmp);
     int rands,rest;
     printf("入栈:"); 
     for(int i = 0;i < 100;i++){
         rands = rand()%1000;
         Push(S,rands);
         printf("%d \n",rands);        
     }
     tmp =  reverseStack(S);
     printf("\n 颠倒栈: "); 
     while(!isEmpty(tmp)){
          Pop(tmp,rest);
          printf("%d \n",rest);   
     }
     system("pause");         
     return 0;      
} 

2.思路2:假如栈的元素为1,2,3,4,5。其中1为栈底,5为栈顶。则颠倒一个栈的过程可以描述为:颠倒1,2,3,4.然后将元素5放入栈底。

  依次进行这个过程。直到栈为空。

  如何将元素放入栈底呢?

  仔细分析后发现,就是另一个递归的过程。

  即:if(栈为空){

                那么直接push。此刻元素就是在栈底。

          }else{

                 否则。弹出栈顶元素。将待push元素放入栈底。然后将原栈顶元素push进栈中即可。

          }


此思路的完整代码如下:


void addToBottom(sqStack &S,SElemType node){
    if(isEmpty(S)){
         Push(S,node); 
    }else{
         SElemType tmp ;
         Pop(S,tmp);
         addToBottom(S,node);
         Push(S,tmp);      
    }   
} 

void reverStack(sqStack &S){
    SElemType node;
    if(!isEmpty(S)){
        Pop(S,node);
        reverStack(S);
        addToBottom(S,node);               
    }        
} 

 
main(){
     sqStack S;
     InitStack(S);
     int rands,rest;
     printf("入栈:"); 
     for(int i = 0;i < 100;i++){
         rands = rand()%1000;
         Push(S,rands);
         printf("%d \n",rands);        
     }
     reverStack(S);
     printf("\n 颠倒栈: "); 
     while(!isEmpty(S)){
          Pop(S,rest);
          printf("%d \n",rest);   
     }
     system("pause");         
     return 0;      
}


你可能感兴趣的:(【学习点滴-数据结构-栈&队列】 颠倒一个栈。)