栈是一种具有特殊操作规则的线性数据结构,可以看成一个具有一端封闭的线性表,在顺序栈中,栈的存储空间是在数组中开辟的,而链栈的存储空间则是由若干个数据结点构成,各个数据结点通过指针相连。
因为栈具有结构简单,操作规则严格的特点,且栈顶指针总是指向栈顶元素的下一个位置,栈底和栈顶指针不断变化,所以栈的存取操作极为方便快捷,就算是大数据量也可以极快速度进行存储。
栈的一种非常重要的特性是后进先出,即最后进入的元素一定最先被弹出。这也是栈存取速度快的一个原因。原因在于插入一个元素时,首先将元素插入栈顶,这个过程非常快速地完成,因为栈顶的位置总是固定的,直接修改栈顶指针就完成了插入。在进行弹出操作时,直接弹出栈顶的元素即可,同样非常快捷,时间复杂度为O(1)。
栈的存取速度还受到计算机硬件结构的影响,其中一个重要原理是局部性原理。局部性原理指的是,当程序访问某个存储地址的时候,它往往会利用附近的存储地址。这个原理主要分为两种,时间局部性和空间局部性。
时间局部性指的是,如果程序通过一个内存地址访问了一个数据,不久之后,它很可能再次访问该地方存储的信息。栈的特点就是尽可能地利用时间局部性。当栈顶改变时,它指向的地址会改变,但是被弹出的栈顶元素所占用的空间并没有被释放,下一次插入元素时,这块空间就可以再次被利用,从而减少了内存的频繁访问。
空间局部性指的是,一旦程序访问了一个地址单元,那么它很可能在不远的将来使用其附近的存储单元。因此,栈内元素是一个连续的存储结构,在连续存储的空间中,遵循空间局部性的特点,程序访问栈内的一个元素时,下一个元素的地址就在它边上,因此,CPU内部的Cache这种存储成本很高的空间,遵循的正是空间局部性原理,存储频繁使用的数据,加快访问速度。
栈可以由静态分配和动态分配两种方式实现。静态分配指的是,预先分配一个固定大小的空间,然后将这块空间中的数据进行操作。这种方式运算速度快,但是空间利用效率低,因为它无法满足不同场景中的需求。动态分配则相对灵活,可以根据不同的需要对空间大小进行动态调整,因此使用动态内存分配的栈在效率和空间利用率方面都要更为出色。
传统的内存分配方式是基于操作系统提供的堆内存进行调用,但是堆内存分配所耗费的时间比较长,效率低下。因此,在实际应用中,一些高性能的栈会采用专门的内存分配策略,如mmap、mremap等,这些策略所使用的内存分配方式速度更快、效率更高。