Common Lisp中的数组,列表和哈希表

时间:2018-01-14 22:41:33

标签: arrays list common-lisp big-o sbcl

我想知道Common Lisp中的数组,列表和哈希表有什么区别。也就是说,我知道如何在语法上实现和使用它们。我也知道围绕这三种数据类型的计算机科学理论。

我想知道的是什么是Common-Lisp特定的实现?应该如何使用它们来优化性能代码(空间和时间)? Common Lisp中的这些数据结构是否存在任何特性?他们在运行时有多贵?

1 个答案:

答案 0 :(得分:7)

不同之处在于实施后的实际实施和性能(根据O(size)定义)。

Lists

列表是作为链表实现的,因此它们可以具有复杂的嵌套和数据共享。

  1. 添加到开头 - O(1)push
  2. 添加到最后 - O(n)append
  3. 随机访问 - O(n)nth
  4. 因为Lisp使用cons-based trees 为了表示其代码,可以预期链表相对较快 (即上面O(n)中的常数应该很小。)

    Arrays

    数组作为向量(内存的连续部分)实现,multi-dimensional arrays顶部有vectors(索引算法自动完成)。 数组也可以share storage

    1. 添加到开头 - O(n)(需要循环移动数据)
    2. 添加到最后 - O(1)vector-push-extend) - 平均而言,如果您使用fill-pointer& c。
    3. 随机访问 - O(1)aref
    4. 如果您使用specialized arrays 避免装箱,你应该知道数据可能在访问时被装箱。 例如,如果v具有类型(simple-array double-float (5)),那么(aref v 2)可能必须分配内存来设置返回值(编译器) 可以消除一些此类分配,但您需要注意 危险)。

      Hash Tables

      散列表完全不同 - 它们 sequences,因此它们允许从任意数据(而不是序列的整数索引)映射,以及访问(读取和写入)是O(1)

      哈希表可以与association listsproperty lists进行比较(这对于小表来说可以是一个很好的选择)。

      哈希表的主要考虑因素是

      1. 正确选择测试功能
      2. 哈希函数的质量
      3. 垃圾收集的影响
      4. 例如,许多实现都会哈希所有 standard-class个实例 同一个存储桶,使您的哈希表作为列表执行。

        如果使用eq哈希表,则实现可以使用对象地址 在内存中作为(源)的哈希,如果它有一个复制垃圾 收集器,它将必须重新散列每个GC上的所有哈希表。

        您可能会发现最好将字符串用作哈希表键,因为它们是 通常哈希最好。 这是因为packages是, 本质上,glorified字符串哈希表挂钩 reader,所以实现是 通常要确保它们非常好。