数据结构——堆栈

本文详细介绍了堆栈的基本概念,包括定义、特性、基本操作,以及顺序栈和链式栈的区别。堆栈遵循后进先出原则,常见操作有栈初始化、进栈、出栈、读取栈顶元素等。此外,文章还探讨了堆栈在括号匹配问题中的应用,并给出了解决方案的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                     数据结构——堆栈

  (一)堆栈

        1.定义:

          栈的定义:栈是插入和删除只能在其一端进行的线性表。并按后进先出的原则进行操作。
          栈顶:进行插入、删除的一端;
          栈底:另一端;
          空栈:表中没有元素时。

        2.特性:后进先出性、封闭性

        3.基本操作:

                (1)栈初始化
                (2)进栈  Push
                (3)出栈  Pop
                (4)读取栈顶元素 Peek
                (5)判栈空  StackEmpty
                (6)判栈满 StackFull
                (7)置空栈 

  (二)顺序栈

   1.定义

顺序栈AStack的类定义
template < class T >			
class AStack {
	private:
            int size ;		// 数组的规模
            T * stackArray ; 	// 存放堆栈元素的数组
            int top ; 		// 栈顶所在数组元素的下标
	public:
           AStack ( int MaxStackSize ) 	// 构造函数
              { size = MaxStackSize ;             stackArray = new T [MaxStackSize] ; top = -1 ; }
            ~AStack ( ) { delete [ ] stackArray ; }  // 析构函数
           bool Push ( const T& item ) ; // 向栈顶压入一个元素
           bool Pop ( T & item ) ; 	// 从栈顶弹出一个元素
           bool Peek ( T & item ) const ; 	// 存取栈顶元素
           int IsEmpty ( void ) const  { return top = = -1 ; }	// 检测栈是否为空
           int IsFull ( void ) const { return top   size  1 ; } // 检测栈是否为满
           void clear ( void ) { top1 ; } 	// 清空栈
} ;

     2.入栈

bool Stack<T>::Push(const T &item)
{
    if(isFull())
    return false;
    
    StackArrayt[++top]=item;
    return true;
}

    3.出栈

bool Stack<T>::Pop(const T &item)
{
    if(isEmpty())
    return false;
    
    item=StackArray[top--];
    return true;
}


    4.读取栈顶元素

bool Stack<T>::Peek( T & item)
{
if(isEmpty())
    return false;
item=StackArray[top];
return true;
}


     (三)链式栈

1.定义

template < class T >			
class LStack{
	private : 
		SLNode <T> * top ;	// 栈顶指针指向表头
	public :
         LStack ( ) { top = NULL ; } // 构造函数
       ~LStack ( ) { clear ( ) ; }  // 析构函数
        void clear ( ) ;  		// 清空栈
        bool Push ( const T& item ) ; // 向栈顶压入一个元素
        bool Pop ( T & item ) ; 	// 从栈顶弹出一个元素
        bool Peek ( T & item ) const ;	 // 读取栈顶元素
        int IsEmpty ( void ) const { return top = = NULL ; }  // 检测栈是否为空
} ;

2.入栈

bool Push(const T&item)
{
top=new SLNode<T> (item,pop);
return true;
}


3.出栈

bool Pop(const T&item)
{
if(isEmpty()) {
cout<<"Poping from an empty stack!"<<endl;
return false;
}
item =top->data;
SLNode<T> *temp=top;
top=top->next;
delete temp;
return true;
}


4.读取栈顶元素

(代码懒得贴了)


(四)顺序栈和链式栈的比较

1.在空间复杂性上,顺序栈必须初始就申请固定的空间,当栈不满时,必然造成空间的浪费;链式栈所需空间是根据需要随时申请的,其代价是为每个元素提供空间以存储其next指针域。
2.在时间复杂性上,对于针对栈顶的基本操作(压入、弹出和栈顶元素存取),顺序栈和链式栈的时间复杂性均为O(1) . 


(五)堆栈的应用

1.括号匹配问题:

       高级语言程序设计中的各种括号应该匹配,例如:“(” 与 “)”匹配、“[”与 “]” 匹配、“{”与 “}” 匹配等。字符串{a=(b*c}+free( ) ]中的括号就没有匹配上,因为串中第一个关括号 “}” 和最近的未匹配开括号 “(” 不匹配。

    void main ( ) 
	{
	LStack<char> bracket ;   // 声明一个链式栈对象
	char read_in = cin.get() ;    	
	bool is_matched = true ;
	while ( is_matched && read_in != '\n') 
    {
	  if ( read_in = = '{' || read_in = = '[' || read_in = = '(' ) /*若输入开括号,则将其压入栈*/
		bracket.push ( read_in ) ;
        else if ( read_in = = '}' || read_in = =']' || read_in = = ')' ) /* 若输入关括号,则检测是否匹配*/
               { 
			      if ( bracket. IsEmpty () ) 
                     { cout << “Unmatched closing bracket ” << read_in << “is 
                       detected”<<endl ;
	                   is_matched = false ; return ; 
					   }
	              char open_bracket ;
                  bracket.pop (open_bracket) ;
             	  is_matched = ( open_bracket = = '(' && read_in = = ')' )|| ( open_bracket = ='[' && read_in = = ']' ) || ( open_bracket = = '{' && read_in = = '}' )
	              if ( ! is_matched )
                      {   
					  cout<< “Bad match ”<< read_in<<open_bracket<<endl ;
                      return ;
					  	}
               }
     read_in = cin.get() ;
  }
// 若堆栈中仍有开括号,说明匹配失败,因为已无关括号与之匹配
   if ( ! bracket. IsEmpty () )
      cout<< “Unmatched opening bracket detected. ”<<endl ; 
      return ;          
}

2.将十进制数转换成其它进制数

   (1)步骤

      a.十进制整数 x 除以基数 r,所得整余数是 r 进制数 y 的最低位 y0,放入堆栈;
      b.用 x除以 r 的整数商,除以 r,所得整余数是 y 的次低位 y1,放入堆栈;
      c.依此类推,
      d.直到商为 0 ,所得整余数是 y 的最高位ym,放入堆栈;
      e.此时,栈中的 m+1 个 r 进制数即为所得。 

   (2)实现

    #include <stdio.h>    
    #include <malloc.h>   //malloc     
    #include <math.h>     //含有overflow    
    #define S_SIZE 100   //栈的空间大小      
    typedef struct SqStack{    
     int top;  //栈顶    
     int maxtop;   //栈最大的存储空间    
     int *stack;    
    }SqStack;    
      
  //初始化空栈     
    void InitStack(SqStack &S)    
    {  
        S.stack=(int *)malloc(S_SIZE*sizeof(int));  //动态申请一维数组   
        S.maxtop=S_SIZE;    
        S.top=-1;  
    }    
  
//判断空栈  
    int StackEmpty(SqStack &S)    
    {    
       if(S.top==-1)    
           return 1;    
       else    
           return 0;    
    }     
//判断栈满  
    int  StackFull(SqStack &S)  
    {  
       if(S.top==S.maxtop)    
           return 1;    
       else    
           return 0;    
    }  
   
    //进栈  
    void push(SqStack &S,int x)    
    {   
      if(StackFull(S))  
        printf("overflow\n");  
      S.stack[++S.top]=x;   
    }    
    //出栈  
    int pop(SqStack &S)    
    {  
      int x;  
      if(StackEmpty(S))  
         printf("underflow\n");  
      x=S.stack[S.top];   
      S.top--;  
      return x;  
    }   
    //进制转化函数  
    void convert(SqStack &S,int N,int n)    
    {    
      int i,x;   
      do     
      {  
        push(S,N%n);    
        N/=n;    
      } while (N!=0);     
        
      while(!StackEmpty(S))    
      {   
        x=pop(S);  
        if(x>9) //十六进制时输出字母    
        {  
            x=x+55;    
            printf("%c",x);  
        }    
        else    
            printf("%d",x);    
      }    
      printf("\n");    
    }    
    //清空栈  
   void StackClear(SqStack &S)  
   {  
      S.top=-1;  
   }  
   int main()    
    {   
        int n,N;//要转换成的进制数和要转换的数   
        SqStack s;   
        scanf("%d%d",&n,&N) ;  
                InitStack(s);  
        printf("%d转换为%d进制后为:\n",n,N);    
        convert(s,n,N);      
                StackClear(s);  
                return 0;  
 }  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值