【C语言】数据结构-栈

本文详细介绍了如何使用C语言构建栈数据结构,包括栈的分类、接口总览及顺序表形式的具体接口实现,如初始化、销毁、压栈、出栈等操作。通过实例展示了栈的后进先出特性,并探讨了链表和顺序表两种实现方式的优缺点。

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

主页:114514的代码大冒险

qq:2188956112(欢迎小伙伴呀hi✿(。◕ᴗ◕。)✿ )

Gitee:庄嘉豪 (zhuang-jiahaoxxx) - Gitee.com


【声明】本文会出现一些其他数据结构的名称及相关名词,如果不了解相关数据结构自行忽略相应内容即可,本文在创建时秉承着联动其他数据结构的同时,又不影响初学数据结构的朋友能够完成文章主题内容的学习

引入

栈是一种线性表(如果不懂线性表,可以暂时将其理解为数组),但这不是普通的线性表,数据只能从固定一端进入,并在这一端拿出,这一端我们称之为栈顶,而另一端则为栈底 

数据存取遵循后进先出(LIFO - Last In First Out) ,类似于在烧杯中放置与其口径略小的木块:

入栈---也叫压栈(存入数据于栈栈中):

 出栈---退栈(从栈中取出数据):

类似的在生活中还有子弹夹(先安装的子弹靠后发射),刷洗盘子时,依次把每个洗净的盘子放到洗好的盘子上

于是乎,我们这篇文章主要来讲解如何用【c语言】搭建一个栈

分为  <栈-相关接口总览>  


栈-分类

栈是一种特殊的线性表:

(这部分如果没有对顺序表和链表的学习,可以自行略过,不会影响下文的学习) 

由上图可知,栈可以是个特殊的链表,也可以是个特殊的顺序表

如果是个链表:

 【解释】链表的尾删每次都需遍历整个链表,效率太低,所以我们选择表头作为栈顶

如果是个顺序表:

【解释】顺序表的尾删效率要比头删(把除头位置以外的数据向前挪动一个单位)高,所以我们选择以表尾作栈顶 

【比较】两种实现都差不多,但是相比较而言顺序表的形式更优一点,因为链表的每一个节点都需要单独申请动态内存,多次申请产生较多的内存碎片,消耗也大一些,而顺序表则在这方面优于链表

栈-相关接口总览

typedef int STDataType;

typedef struct Stack
{
    STDataType* a;
    int top;
    int capacity;
}ST;//栈的单元组成结构


void StackInit(ST* ps); //初始化栈
void StackDestroy(ST* ps); //销毁栈

void StackPush(ST* ps,STDataType x); //压栈
void StackPop(ST* ps);//删除栈顶数据
STDataType StackTop(ST* ps);//取出栈顶数据
int StackSize(ST* ps);//栈的大小
bool StackEmpty*(ST* ps);//判断栈是否为空

接口就是函数)   

栈-具体接口实现(以顺序表的形式)

我们用top表示栈顶位置的下一个
capacity表示栈的总容量

类似下图这般:

初始化

void StackInit(ST* ps)
{
    assert(ps);
    ps->a = NULL;
    ps->top = 0;
    ps->capacity = 0;
}

销毁

void StackDestroy(ST* ps)
{
    assert(ps);
    free(ps->a);
    ps->a = NULL;
    ps->capacity = ps->top = 0;
    
}

压栈

void StackPush(ST* ps,STDataType x)
{
    assert(ps);

    if(ps->top == ps->capacity)
    {
        int newCapacity = ps->capacity == 0 ? 4:ps->capacity* 2;
        //三目操作符,如果容量为0,我们将将其变为4,不为零,则将容量二倍
        STDataType* tmp = realloc(ps->a,size0f(STDataType)*newCapacity);
        if(tmp == NULL)
        {
            printf("realloc fail\n");
            exit(-1);//申请内存失败,退出程序
        }
        
        ps->a[ps->top] = x;//栈顶存放数据
        ps->top++;//使top再次指向栈顶的下一个位置

    }
}

出栈

void StackPop(ST* ps)
{
    assert(ps);

    assert(ps->top > 0);
    ps->top--;//top表示栈顶的下一个位置,top往后退一个单位
              //栈顶也往后退一个单位


}

取出栈顶数据

STDataType StackTop(ST* ps)
{
    assert(ps);
    assert(ps->top > 0);
    return ps->a[ps->top - 1];

}

判断栈是否为空

bool StackEmpty*(ST* ps)
{
    assert(ps);

  //  if(ps->top > 0)
  //  {
  //      return ture;
  //  }
  //  else
  //  {
  //      return false;
  //  }
  //  被注释掉的是另一种实现该接口的逻辑
    return ps->top == 0;
  //  我们选择简单一点,直接执行一个判断语句,返回判断语句的结果
}

总文件

头文件

typedef int STDataType;

typedef struct Stack
{
    STDataType* a;
    int top;
    int capacity;
}ST;


void StackInit(ST* ps); 
void StackDestroy(ST* ps); 

void StackPush(ST* ps,STDataType x); 
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty*(ST* ps);

接口文件

void StackInit(ST* ps)
{
    assert(ps);
    ps->a = NULL;
    ps->top = 0;
    ps->capacity = 0;
}
void StackDestroy(ST* ps)
{
    assert(ps);
    free(ps->a);
    ps->a = NULL;
    ps->capacity = ps->top = 0;
    
}

void StackPush(ST* ps,STDataType x)
{
    assert(ps);

    if(ps->top == ps->capacity)
    {
        int newCapacity = ps->capacity == 0 ? 4:ps->capacity* 2;
        STDataType* tmp = realloc(ps->a,size0f(STDataType)*newCapacity);
        if(tmp == NULL)
        {
            printf("fealloc fail\n");
            exit(-1);
        }
        
        ps->a[ps->top] = x;
        ps->top++;

    }
}
void StackPop(ST* ps)
{
    assert(ps);

    assert(ps->top > 0);
    ps->top--;


}



STDataType StackTop(ST* ps)
{
    assert(ps);
    assert(ps->top > 0);
    return ps->a[ps->top - 1];

}
int StackSize(ST* ps)
{
    
}



bool StackEmpty*(ST* ps)
{
    assert(ps);

  //  if(ps->top > 0)
  //  {
  //      return ture;
  //  }
  //  else
  //  {
  //      return false;
  //  }

    return ps->top == 0;
}

写在最后

我真诚的希望你能够阅读本文时,得到一些帮助与启发

这是我第一次尝试省去每段接口的单独思路分析,而是直接对代码进行较为详细的注释

文中当然还存在各种各样的不足,欢迎私信告诉我,

同时,我知道我的表达水平有限,语言也还不够通俗易懂,所以我随时欢迎你的私信

我是真的掌握了这部分的内容才将它写出来,所以,有任何疑问,call me!!

评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值