数据结构之栈

栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。

栈的结构:

实现栈的方式

实现栈的方式有两种:顺序表和链表

链表的优缺点:

优点:

  1. 任意位置插入删除O(1)

  2. 按需申请释放空间

缺点:

  1. 不支持下标随机访问

  2. CPU高速缓存命中率会更低

先说链表实现栈的缺点:

  1. 额外内存开销:链表实现的栈需要为每个节点分配空间来存储数据和指针。相比于数组实现的栈,链表实现需要额外的内存开销来维护节点之间的指针关系,可能导致内存碎片化。

  2. 动态内存分配:链表实现的栈需要通过动态内存分配来创建和释放节点。这涉及到频繁的内存分配和释放操作,可能导致内存管理的复杂性和性能开销。在某些情况下,可能会出现内存分配失败或内存泄漏的问题。

  3. 指针操作开销:链表实现的栈需要通过指针进行节点之间的连接操作。这包括插入和删除节点时的指针修改,可能涉及到多个指针的更新。相比于数组实现的栈,链表实现的栈需要更多的指针操作,可能会带来一定的性能开销。

  4. 随机访问的限制:链表是一种顺序访问的数据结构,无法像数组一样通过索引进行随机访问。如果需要在栈中进行随机访问元素,链表实现的栈可能不太适合,而数组实现的栈更具优势。

顺序表的优缺点:

优点:

  1. 尾插尾删效率不错。

  2. 下标的随机访问

  3. CPU高速缓存命中率会更高

缺点:

  1. 前面部分插入删除数据,效率时O(N),需要挪动数据。

  2. 空间不够,需要扩容。

a. 扩容是需要付出代价的

b. 一般还会伴随空间浪费

顺序表实现栈的优点:

  1. 内存连续性:顺序表在内存中是连续存储的,相比于链表的动态内存分配,顺序表的元素在物理上更加紧凑。这样可以减少内存碎片化,提高内存的利用效率。

  2. 随机访问:顺序表可以通过索引直接访问栈中的元素,具有随机访问的能力。这意味着可以快速访问栈中任意位置的元素,而不需要遍历整个链表。

  3. 操作简单高效:顺序表的插入和删除操作只涉及元素的移动,不需要额外的指针操作和动态内存分配。这使得操作相对简单高效,并且在某些情况下比链表实现更快。

  4. 空间效率:相比于链表实现,顺序表不需要额外的指针来维护节点之间的连接关系,因此可以节省一定的空间开销。只需要存储元素本身和栈顶指针即可。

综上所述,用顺序表实现栈更好。

栈的实现

  1. 栈的定义

    typedef int STDataType;
    typedef struct Stack
    {
    STDataType* a;
    int top;//栈顶
    int capacity;//栈的容量
    }ST;

  2. 接口函数

    // 初始化栈
    void STInit(ST* pst);

    // 入栈
    void STPush(ST* pst, STDataType data);

    // 出栈
    void STPop(ST* pst);

    // 获取栈顶元素
    STDataType STTop(ST* pst);

    // 获取栈中有效元素个数
    int STSize(ST* pst);

    // 检测栈是否为空,如果为空返回true,如果不为空返回false
    bool STEmpty(ST* pst);

    // 销毁栈
    void STDestroy(ST* pst);

  3. 栈的初始化

    void STInit(ST* pst)
    {
    assert(pst);//防止敲代码的人传过来是NULL指针

    复制代码
     pst->a = NULL;//栈底
     
     //top不是数组下标,不能理解成数组下标,因为栈只能拿到栈顶的元素,而数组可以随机访问拿到中间元素
     //pst->top=-1;//指向栈顶元素
     
     pst->top = 0;//指向栈顶元素的下一个位置
     pst->capacity = 0;

    }

  4. 销毁栈

    void STDestroy(ST* pst)
    {
    assert(pst);
    free(pst->a);
    pst->a = NULL;
    }

  5. 检测栈是否为空

    bool STEmpty(ST* pst)//栈为空返回true,不为空返回false
    {
    return pst->top == 0;
    }

  6. 入栈

    void STPush(ST* pst,STDataType x)
    {
    if (pst->top == pst->capacity)
    {
    int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;

    复制代码
     	STDataType* tmp = (STDataType*)realloc(pst->a, newCapacity * sizeof(STDataType));
     	if (tmp == NULL)
     	{
     		perror("realloc fail");
     		return;
     	}
     	pst->a = tmp;//返回的是realloc出来的内存块的地址
     	pst->capacity = newCapacity;//把扩容后的空间大小赋值给栈容量
     }
     pst->a[pst->top] = x;//先放值
     pst->top++;//再++

    }

  7. 出栈

复制代码
void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}
  1. 获取栈顶元素
复制代码
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
 
	return pst->a[pst->top - 1];
}
  1. 获取栈中有效元素个数

    int STSize(ST* pst)
    {
    assert(pst);
    return pst->top;
    }

相关推荐
爱喝热水的呀哈喽24 分钟前
Java 集合 Map Stream流
数据结构
Dovis(誓平步青云)34 分钟前
【数据结构】排序算法(中篇)·处理大数据的精妙
c语言·数据结构·算法·排序算法·学习方法
Touper.1 小时前
L2-003 月饼
数据结构·算法·排序算法
SsummerC13 小时前
【leetcode100】每日温度
数据结构·python·leetcode
jingshaoyou13 小时前
Strongswan linked_list_t链表 注释可独立运行测试
数据结构·链表·网络安全·list
逸狼16 小时前
【Java 优选算法】二分算法(下)
数据结构
云 无 心 以 出 岫19 小时前
贪心算法QwQ
数据结构·c++·算法·贪心算法
姜威鱼20 小时前
蓝桥杯python编程每日刷题 day 21
数据结构·算法·蓝桥杯
神里流~霜灭21 小时前
蓝桥备赛指南(12)· 省赛(构造or枚举)
c语言·数据结构·c++·算法·枚举·蓝桥·构造
双叶83621 小时前
(C语言)单链表(1.0)(单链表教程)(数据结构,指针)
c语言·开发语言·数据结构·算法·游戏