Stack的三种含义

原文网址:http://www.ruanyifeng.com/blog/2013/11/stack.html

 

 

学习编程的时候,经常会看到stack这个词,它的中文名字叫做"栈"。

理解这个概念,对于理解程序的运行至关重要。容易混淆的是,这个词其实有三种含义,适用于不同的场合,必须加以区分。

含义一:数据结构

stack的第一种含义是一组数据的存放方式,特点为LIFO,即后进先出(Last in, first out)。

数据结构stack

在这种数据结构中,数据像积木那样一层层堆起来,后面加入的数据就放在最上层。使用的时候,最上层的数据第一个被用掉,这就叫做"后进先出"。

与这种结构配套的,是一些特定的方法,主要为下面这些。

  • push:在最顶层加入数据。
  • pop:返回并移除最顶层的数据。
  • top:返回最顶层数据的值,但不移除它。
  • isempty:返回一个布尔值,表示当前stack是否为空栈。

含义二:代码运行方式

stack的第二种含义是"调用栈"(call stack),表示函数或子例程像堆积木一样存放,以实现层层调用。

下面以一段Java代码为例(来源)。


class Student{
    int age;              
    String name;      

    public Student(int Age, String Name)
    {
        this.age = Age;
        setName(Name);
    }
    public void setName(String Name)
    {
        this.name = Name;
    }
}

public class Main{
    public static void main(String[] args) {
            Student s;           
            s = new Student(23,"Jonh");
    }
}

上面这段代码运行的时候,首先调用main方法,里面需要生成一个Student的实例,于是又调用Student构造函数。在构造函数中,又调用到setName方法。

调用栈

这三次调用像积木一样堆起来,就叫做"调用栈"。程序运行的时候,总是先完成最上层的调用,然后将它的值返回到下一层调用,直至完成整个调用栈,返回最后的结果。

含义三:内存区域

stack的第三种含义是存放数据的一种内存区域。程序运行的时候,需要内存空间存放数据。一般来说,系统会划分出两种不同的内存空间:一种叫做stack(栈),另一种叫做heap(堆)。

内存区域stack

它们的主要区别是:stack是有结构的,每个区块按照一定次序存放,可以明确知道每个区块的大小;heap是没有结构的,数据可以任意存放。因此,stack的寻址速度要快于heap。

内存区域heap

其他的区别还有,一般来说,每个线程分配一个stack,每个进程分配一个heap,也就是说,stack是线程独占的,heap是线程共用的。此外,stack创建的时候,大小是确定的,数据超过这个大小,就发生stack overflow错误,而heap的大小是不确定的,需要的话可以不断增加。

根据上面这些区别,数据存放的规则是:只要是局部的、占用空间确定的数据,一般都存放在stack里面,否则就放在heap里面。请看下面这段代码(来源)。


public void Method1()
{
    int i=4;

    int y=2;

    class1 cls1 = new class1();
}

上面代码的Method1方法,共包含了三个变量:i, y 和 cls1。其中,i和y的值是整数,内存占用空间是确定的,而且是局部变量,只用在Method1区块之内,不会用于区块之外。cls1也是局部变量,但是类型为指针变量,指向一个对象的实例。指针变量占用的大小是确定的,但是对象实例以目前的信息无法确知所占用的内存空间大小。

这三个变量和一个对象实例在内存中的存放方式如下。

内存空间stack实例

从上图可以看到,i、y和cls1都存放在stack,因为它们占用内存空间都是确定的,而且本身也属于局部变量。但是,cls1指向的对象实例存放在heap,因为它的大小不确定。作为一条规则可以记住,所有的对象都存放在heap。

接下来的问题是,当Method1方法运行结束,会发生什么事?

回答是整个stack被清空,i、y和cls1这三个变量消失,因为它们是局部变量,区块一旦运行结束,就没必要再存在了。而heap之中的那个对象实例继续存在,直到系统的垃圾清理机制(garbage collector)将这块内存回收。因此,一般来说,内存泄漏都发生在heap,即某些内存空间不再被使用了,却因为种种原因,没有被系统回收。

(完)

 

### numpy 中 np.stack 与 np.dstack含义及用法 #### np.stack `np.stack` 是一个用于沿指定轴堆叠一系列数组的函数。它要求所有输入数组具有相同的形状,并将它们沿着指定的新轴合并,从而增加一个维度[^1]。 例如: ```python import numpy as np a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) result = np.stack((a, b), axis=0) print(result) # 输出: # [[1 2 3] # [4 5 6]] ``` 在这个例子中,`axis=0` 表示在第一个维度上堆叠数组,因此结果是一个形状为 `(2, 3)` 的二维数组。 #### np.dstack `np.dstack` 是一种特殊的堆叠方式,它总是沿着深度方向(即第三个维度)堆叠数组。这相当于将多个二维数组堆叠成一个三维数组[^3]。 例如: ```python import numpy as np a = np.array([[1, 2], [3, 4]]) b = np.array([[5, 6], [7, 8]]) result = np.dstack((a, b)) print(result) # 输出: # [[[1 5] # [2 6]] # # [[3 7] # [4 8]]] ``` 在这里,`np.dstack` 将两个形状为 `(2, 2)` 的二维数组堆叠成一个形状为 `(2, 2, 2)` 的三维数组。 --- ### 如何将 `np.zeros` 和 `np.meshgrid` 的输出组合成坐标数组 可以使用 `np.dstack` 将 `np.meshgrid` 生成的网格与 `np.zeros` 创建的零数组组合起来,形成一个包含坐标的三维数组。 以下是一个完整的代码示例: ```python import numpy as np # 使用 np.meshgrid 生成二维网格 x = np.linspace(0, 1, 5) y = np.linspace(0, 1, 5) X, Y = np.meshgrid(x, y) # 创建一个与 X 和 Y 形状相同的零数组 Z = np.zeros_like(X) # 使用 np.dstack 将 X、Y 和 Z 合并为一个三维坐标数组 coordinates = np.dstack((X, Y, Z)) print("X:") print(X) print("Y:") print(Y) print("Z:") print(Z) print("Coordinates (shape: {}):".format(coordinates.shape)) print(coordinates) ``` #### 输出结果 运行上述代码后,输出结果如下: ``` X: [[0. 0.25 0.5 0.75 1. ] [0. 0.25 0.5 0.75 1. ] [0. 0.25 0.5 0.75 1. ] [0. 0.25 0.5 0.75 1. ] [0. 0.25 0.5 0.75 1. ]] Y: [[0. 0. 0. 0. 0. ] [0.25 0.25 0.25 0.25 0.25] [0.5 0.5 0.5 0.5 0.5 ] [0.75 0.75 0.75 0.75 0.75] [1. 1. 1. 1. 1. ]] Z: [[0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.]] Coordinates (shape: (5, 5, 3)): [[[0. 0. 0. ] [0.25 0. 0. ] [0.5 0. 0. ] ... [1. 1. 0. ]]] ``` 在这个例子中,`coordinates` 是一个形状为 `(5, 5, 3)` 的三维数组,其中每个元素表示一个三维坐标点 \((x, y, z)\)[^3]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值