【问题标题】:What is the point of PHP's SplDoublyLinkedList class, and more importantly, Linked Lists in general?PHP 的 SplDoublyLinkedList 类有什么意义,更重要的是,一般来说,链接列表有什么意义?
【发布时间】:2011-04-27 04:06:17
【问题描述】:

为了提高我的编程能力,我对The Standard PHP Library 进行了非常轻微的研究。这导致我发现了SplDoublyLinkedList 类。从那里我阅读了维基百科上Linked ListsDoubly Linked Lists 的描述。

我了解它们的工作原理......但我无法想出我们为什么需要它的原因——或者更好的是 SplDoublyLinkedList 的实际示例,因为我们在 PHP 中具有索引和关联数组。

链表在 PHP 的内外使用是怎样的?

【问题讨论】:

    标签: php data-structures linked-list spl


    【解决方案1】:

    也许您正在编写一个 Web 应用程序,以使网站看起来像一本书(例如在线 epub)。可折叠的 TOC(目录)将提供随机访问。链接列表将提供一种方便的方式来实现“下一页”和“上一页”按钮。 Next 和 Previous 可以以其他方式实现。链表会让它变得轻而易举。

    【讨论】:

      【解决方案2】:

      根据Wikipedia

      链表的主要好处 在一个传统的阵列是 链接项目的顺序可能是 不同于数据的顺序 项目存储在内存或磁盘上。 因此,链表允许 在任意位置插入和删除节点 列表中的点,具有常数 操作次数。

      另一方面,链表由 自己不允许随机访问 数据,或任何形式的有效 索引。因此,许多基本操作 ——比如获取最后一个节点 列表,或找到一个节点 包含给定的数据,或定位 新节点应该在的地方 已插入 — 可能需要最扫描 列表元素。

      所以要回答你的问题,我不知道。 :)

      【讨论】:

      • 它的意思是链接的楦子具有快速的插入和删除,而在传统的数组中,元素必须被打乱,或者必须复制和扩展数组。然而,PHP 的“数组”不是传统的数组。
      • 有人发现了SplDoublyLinkedList的用途:从php 5.3.0到php7.*到php8.alpha,你可以使用SplDoublyLinkedList从www-data访问升级到root如果您正在运行 php-fpm,则 i> 访问:github.com/cfreal/exploits/blob/master/… / bugs.php.net/bug.php?id=81026 - 假设您在共享虚拟主机上,他们拒绝为您提供 shared的 root 访问权限> webhost 服务器...或者如果您是 Composer 项目的维护者,并且您的 1 个用户拒绝授予您对其服务器的 root 访问权限...是的
      【解决方案3】:

      你可能是对的,只是它不是很有用。

      理论上链表有很多用途(尤其是跳舞的链接)。但其中大多数涉及将其迭代器存储和克隆到其他地方,从两个以上的方向访问内容,或者拆分和合并列表。 SplDoublyLinkedList 似乎没有这些。

      如果它不是用于算法,一个用途是允许对象在恒定时间内删除某个列表中自身的引用,释放其内存并且在插入后不打乱列表(通过散列或与最后一项交换)或删除。但这需要在这些对象中存储列表的迭代器。

      没有这些功能,它们的行为就像两个双端队列。如果您只需要使用迭代器访问项目,它们就像两个堆栈。在单线程简单情况下,一种更好的方法是使用两个堆栈(可能是固定数组,或同一数组的两端),除非尚未包装在一个类中。每当您希望迭代器移动时,从一个堆栈弹出并将其推送到另一个堆栈,并且一个堆栈的顶部是当前项。如果您还需要访问头部和尾部,则需要将堆栈替换为双端队列。

      但是,如果您想在不知道最大大小的情况下自行实现堆栈或双端队列,或者甚至要分配普通链表的节点(在没有这些库的语言中,如 PHP),那么好的方法是将一些固定数组链接在一起,使用没有这些功能的双向链表。不知何故你仍然需要它。

      PHP 文档本身,就像 Java 文档一样,表明它们应该只是一个支持一些额外奇怪功能的双端队列,甚至不是两个双端队列(我认为)。如果您确实需要双向链表,请不要使用它们。

      【讨论】:

        【解决方案4】:

        SPL 数据结构可减少内存消耗并提高性能。很好的解释:

        数据结构本质上与语言无关,并且作为一组基于数学的逻辑概念存在。这些容器酌情使用不同的算法来最大限度地提高效率。

        例如,如果您不需要关联数组的哈希映射功能——也就是说,如果您没有将数组键用于特定目的而只需要一个枚举数组——SplFixedArray(以前称为 SplFastArray ,目前未记录)可能是合适的替代品。唯一需要注意的是数组的大小是固定的,这意味着您必须在实例化类时指定大小,如果您尝试存储超过该数量的元素,则会发生错误。这就是平均而言,它的性能优于标准 PHP 数组的原因。

        http://web.archive.org/web/20130805120049/http://blueparabola.com/blog/spl-deserves-some-reiteration

        在构成 PHP 解释器的 C 代码中,数组被实现为称为哈希表或哈希映射的数据结构。当数组中包含的值被其索引引用时,PHP 使用散列函数将该索引转换为唯一散列,表示数组中相应值的位置。

        此哈希映射实现使数组能够存储任意数量的元素,并使用数字或字符串键同时提供对所有这些元素的访问。数组因其提供的功能而速度极快,并且是一种出色的通用数据结构。

        在计算机科学中,列表被定义为值的有序集合。链表是一种数据结构,其中列表中的每个元素都包含对列表中其任一侧的一个或两个元素的引用。术语“双向链表”用于指后一种情况。在 SPL 中,它采用 SplDoublyLinkedList 类的形式......当预先不知道要存储的元素数量并且只需要按顺序位置访问元素时,使用列表是有意义的。

        http://matthewturland.com/2010/05/20/new-spl-features-in-php-5-3/

        【讨论】:

        • 这是最好的答案,也是了解这些数据结构用途的好方法。然而,事情并不像这个答案所暗示的那么简单。仅仅基于什么是双链表和什么是哈希表的概念(数组是如何在 PHP 中实现的),人们会期望双链表可以比数组节省大量内存。然而,在我的测试中,我几乎都用完了内存。这让我相信双向链表在 PHP 中的实现非常愚蠢。
        • 我还尝试制作我自己的单链表类,并敏锐地保护记忆。不知何故,我在与使用普通 PHP 数组一样的地方内存不足,这非常奇怪。这让我怀疑 PHP 的内部结构在意想不到的地方使用了 PHP 数组。这只是一个猜测,但不确定还有什么想法。顺便说一句,我使用的是 PHP 5.3.2,所以希望新版本对此更好,但我不知道。关键是,如果您出于性能原因要使用 PHP 数组以外的数据结构,请确保您测量性能以确保它有帮助。
        【解决方案5】:

        首先,SplDoublyLinkedList 是对象,因此

        • 它们可以扩展,因此您可以覆盖它们的方法(例如,您可以返回所有大写的字符串等)
        • 他们实现的接口可以像myfunc( SplDoublyLinkedList $var ) ...一样检查
        • 默认情况下它们作为参考传递

        其次,SplDoublyLinkedList 接受迭代模式,因此您可以随时删除项目,并切换方向,而无需重新排序数组或使代码复杂化:

        SplDoublyLinkedList::IT_MODE_LIFO(堆栈样式)

        SplDoublyLinkedList::IT_MODE_FIFO(队列风格) 迭代器(一个或另一个)

        SplDoublyLinkedList::IT_MODE_DELETE(元素被 迭代器)

        SplDoublyLinkedList::IT_MODE_KEEP(元素被遍历 迭代器)

        以上引用来自http://simpletechinfo.com/SplDoublyLinkedList,其中包含一些代码示例。

        还有其他好处(例如 foreach 不必在内存中复制所有数据等)

        【讨论】:

          【解决方案6】:

          正如其他人所提到的,列表是其他语言中常见的固定数组的替代品。但是一个经常被忽视的重要方面 - 您可以非常有效地从列表中的任何位置插入或删除元素。

          为什么这很重要?假设您有几个要保持在数组中排序的项目,也许这样您以后不必对它们进行排序或只是为了最大限度地减少搜索时间。在这种情况下,列表可能是一个非常强大的工具。特别是对于非常大的数据集。

          【讨论】:

            【解决方案7】:

            它们存在是因为许多来自其他语言的程序员已经习惯了它们,其中数组具有固定大小,并且您必须注意内存管理。
            所以对于 PHP,它们只是另一个工具。它们的实现是因为许多算法和模式在列表上中继,因此不需要将它们更改为 php-arrays。

            【讨论】:

            • 这是基于假设吗?在 SPL 中实现一种不需要的数据结构(仅用于安抚从另一种语言过渡到 PHP 的程序员)似乎有点牵强...
            • 它们是在 SPL 中实现的,因为自定义 php 编写的实现效率要低得多。 php 社区可以在没有它们的情况下生存多年。列表肯定是最重要的数据结构之一。例如,这同样适用于类——你不需要它们来编写程序,但它们确实有帮助,但它们也是一种工具。
            • 好吧,我会咬的。它们不是必需的(很明显,因为我已经很久没有使用它们了),但是你有一个例子说明它们如何让我的生活更轻松吗?您已经将它们与类进行了比较。课程让我的生活轻松了大约 90 亿倍。链表如何以及在哪里适合 PHP?
            • 它们并没有让 PHP 的生活变得更轻松。在 PHP 中,您可以向数组中添加新条目,例如 '$array[] = $object;'无需检查索引和数组大小(我认为是 Java 中的 IndexOutOfBoundException)。但是你不能用任何编译语言来做到这一点。那里的数组有固定的大小。这就是列表发挥作用的地方——它们没有固定的大小,并且可以扩展而无需将完整的数组复制到更大的数组中。要了解真正的优势,您必须了解数组和列表如何在任何编译语言中工作,因为它们的限制性更强。
            • 别误会我的意思...显然是不明白的人。但是你最后的评论让我很困惑。 “他们不会让 PHP 的生活变得更轻松。”和“要了解真正的优势,您必须了解数组和列表如何在任何编译语言中工作。”那么有没有,或者没有真正的优势?
            猜你喜欢
            • 2020-04-17
            • 1970-01-01
            • 2018-06-21
            • 2012-03-22
            • 2015-08-04
            • 1970-01-01
            相关资源
            最近更新 更多