数据结构与算法(5.1)栈(附源码)

在今天的学习中,将会介绍栈和队列的概念,以及其功能的实现,还有其应用场景


在这里插入图片描述

前言

栈是一种特殊的线性表,只允许在固定的一端进行插入和删除操作,这个端叫做栈顶,另一端叫做栈底,栈中元素遵循后进先出原则。
压栈:栈的插入操作叫压栈/入栈1/进栈
出栈:栈的删除操作叫做出栈

这个栈我们怎么理解它呢,他就像一个弹夹一样,每一颗子弹就相当于一个元素,子弹怎么进呢?肯定是先进最里面,再一颗一颗往上垒对吧,那子弹是怎么出弹夹的呢?就是从最顶上的开始,一颗一颗出去对吧,最顶上就相当于栈顶,放子弹是压栈,射击就是出栈了。(砰砰!)
在这里插入图片描述
我们也可以形象的把图画出来一下,方便我们后来实现。
在这里插入图片描述
大概就是这样,下面我们来看看怎么实现,如何实现。

栈的实现

栈也是线性表的一种,那么之前我们学过两种线性表,一种是链表,一种是顺序表。谁更适合栈的实现呢?其实两种都可以,但是如果使用顺序表的话,尾插的时候我们可以直接插入,访问有效节点个数的下标,但如果是单链表,我们压栈的时候就需要遍历一遍才能往里面压栈了。综上,我们直接用线性表实现栈。

1.初始化栈

2.检查容量

3.入栈

4.出栈

5.检查栈是否为空

6.销毁栈

栈的功能不多,也很好理解,就是一种特殊的线性表。

1.初始化栈

初始化之前我们先看看一些声明

typedef int STDataType;    
typedef struct Stack       
{                                                                               
  STDataType* _a;      
  int size;//有效数据个数    
  int _capacity;  // 容量     
}Stack;   

下面是初始化:

// 初始化栈     
void StackInit(Stack* ps)
{                      
  ps->_a = (STDataType *)calloc(DEFSTACKSIZE,sizeof(STDataType));    
  ps->_capacity = DEFSTACKSIZE;    
  ps->size = 0;       
} 

没啥说的,很简单;

2.检查容量

栈也是会到顶的,空间不是无限的,都是我们给的,所以要注意每次插入之前考虑栈的容量问题

void CheckCapacity(Stack* ps)
{
  if(ps->size >=  ps->_capacity)
  {
    ps->_capacity *= 2;
    ps->_a = (STDataType *)realloc(ps->_a,ps->_capacity*sizeof(STDataType));
  }
}

当然,如果这么扩容就会出现空间浪费的问题,这不能避免。

3.入栈

入栈只能从栈顶入,这是栈的规则,我们结构体中的size现在就相当于栈顶的上面,这个位置是没有元素的,所以直接在这个位置插入就好:

void StackPush(Stack* ps, STDataType data)    
{                                                                               
  CheckCapacity(ps);    
  ps->_a[ps->size] = data;    
  ps->size++;                
} 

在这里插入图片描述

4.出栈

// 出栈         
void StackPop(Stack* ps)    
{                                  
  if(ps->size == 0)    
  return ;                    
  ps->size--;                                                                     
}    

出栈就很简单了,直接让size-- ,就代表栈顶元素没了,栈顶向前移一位。

5.检查栈是否为空

// 出栈         
void StackPop(Stack* ps)    
{                                  
  if(ps->size == 0)    
  return ;                    
  ps->size--;                                                                     
}    

由于size就代表有效元素个数,我们直接用就行。

6.销毁栈

// 销毁栈     
void StackDestroy(Stack* ps)
{
  if(ps->_a)
  {
    free(ps->_a);
    ps->_a = NULL;
    ps->size = 0;
    ps->_capacity = 0;
  }
}

销毁栈就和原先顺序表的销毁是一样的。

栈的应用场景

栈由于其后进先出的特性,我们可以用它做一些匹配问题,例如符号匹配问题。

源码

Stack.h

#include<stdio.h>           
#include<stdlib.h>
#include<assert.h>          
                        
typedef int STDataType;
typedef struct Stack
{
  STDataType* _a;                                            
  int _top;   // 栈顶    
  int size;//有效数据个数
  int _capacity;  // 容量 
}Stack;
void CheckCapacity(Stack* ps);                                                    
                            
// 初始化栈 
void StackInit(Stack* ps);
// 入栈 
void StackPush(Stack* ps, STDataType data);
// 出栈           
void StackPop(Stack* ps);
// 获取栈顶元素       
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数 
int StackSize(Stack* ps); 
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps); 
// 销毁栈 
void StackDestroy(Stack* ps); 

Stack.c

#include"Stack.h"
#define DEFSTACKSIZE 100
void CheckCapacity(Stack* ps)
{
  if(ps->size >=  ps->_capacity)
  {
    ps->_capacity *= 2;
    ps->_a = (STDataType *)realloc(ps->_a,ps->_capacity*sizeof(STDataType));
  }
}
// 初始化栈     
void StackInit(Stack* ps)
{                  
  ps->_a = (STDataType *)calloc(DEFSTACKSIZE,sizeof(STDataType));
  ps->_capacity = DEFSTACKSIZE;
  ps->size = 0;             
}                       
// 入栈                
void StackPush(Stack* ps, STDataType data)
{
  CheckCapacity(ps);                                         
  ps->_a[ps->size] = data;
  ps->size++;            
}                         
// 出栈     
void StackPop(Stack* ps)
{                           
  if(ps->size == 0)
  return ;                
  ps->size--;                                                                     
}                                          
// 获取栈顶元素     
STDataType StackTop(Stack* ps)
{                     
  if(ps->size == 0)            
    return (STDataType)0;                                                         

  return ps->_a[ps->size-1];
}
// 获取栈中有效元素个数     
int StackSize(Stack* ps)
{
  return ps->size;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0     
int StackEmpty(Stack* ps)
{
  return ps->size == 0;
}
// 销毁栈     
void StackDestroy(Stack* ps)
{
  if(ps->_a)
  {
    free(ps->_a);
    ps->_a = NULL;
    ps->size = 0;
    ps->_capacity = 0;
  }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值