【问题标题】:How is push()ing and pop()ping defined?push()ing 和 pop()ping 是如何定义的?
【发布时间】:2011-02-17 19:20:28
【问题描述】:

我知道队列/链表的典型实现中的 push() 和 pop() 方法是如何工作的,但我想知道的是您实际定义为 push 还是 pop?什么时候可以命名方法 push()/pop()?是什么让典型 Tree 实现中的 insert()/add() 方法不是 push()?

我的理解是 push()ing 意味着将某些东西放在某个特殊指针指向的位置,而 pop()ping 一个元素意味着将某个对象放在某个指针指向的位置,但它似乎不是明确规定。或者命名是否重要?

【问题讨论】:

  • 你可能会问这样的问题。
  • 大声笑 - 看看有点简单的问题的力量,大规模的回答攻击。

标签: data-structures definition


【解决方案1】:

当引用链表上的操作时,您可以将项目推送到链表上以添加它们。然后,您可以从列表中弹出项目以将其删除。

如果您从添加它们的列表的同一端弹出项目,则您实现了堆栈或后进先出 (LIFO) 数据结构:

如果您从另一端弹出项目,那么您已经实现了一个队列 - 尽管通常术语是“入队”和“出队”。这是一个先进先出 (FIFO) 数据结构:

【讨论】:

  • 哦,漂亮的照片,+1 :)
  • 你也应该把 FIFO 和 LIFO 放在那里。当它是 LIFO 时,你 push/pop,当它是 FIFO 时,你入队/出队。
  • 正如有人在下面指出的那样...... Push/Pop 操作实际上通常应用于“堆栈”,并不总是与“链表”完全相同,而链表可以为您提供队列或堆栈的基础,同样容易,从语义上讲,FIFO/LIFO 标准是你如何决定原来的人在问什么。
【解决方案2】:

术语 push 和 pop 通常用于 stacks,而不是 queueslinked lists。堆栈是一种后进先出 (LIFO) 数据结构;换句话说,首先要删除的是最近添加的项目。推是指将新项目放入堆栈时,弹出是指将其取出。

许多编程语言允许您以任何您想要的方式编写代码,包括对任何和所有数据结构使用名称 push 和 pop,即使这不是您真正在做的事情。但是,我不会推荐它。最好使用其他人使用的术语,以便其他程序员可以阅读您的代码。此外,使用错误的术语可能会导致难以找到工作,并且如果您正在从事项目(工作或开源),也会使与其他程序员交流变得困难。

【讨论】:

    【解决方案3】:

    Pushing 意味着将一个项目放入一个堆栈(数据结构),使其成为堆栈的最顶层项目。 弹出 意味着从堆栈中删除最顶部的项目。 (您经常听到第三个术语,peeking,意思是查看/阅读最上面的项目。)

    当涉及到 queues 时,您通常应该使用术语 enqueueingdequeueing,前者意味着将一个项目附加到一个队列的“后端”,后者意味着从队列中删除“前端”的项目。

    这些定义表明堆栈(如果您在脑海中想象它)在空间上是垂直的,而队列是水平的。另一个区别是堆栈上的操作总是发生在同一端,而队列上的操作总是发生在相反的两端。

    当涉及到链表双端队列(deques)时,术语pushpop 也被使用,例如在 C++ 的 STL 中,您有 push_frontpush_backpop_frontpop_back 等操作。这些只是意味着可以在两端附加或删除项目。


    至于为什么叫 pop 而不是 pull(与 push 相比)...好问题。

    【讨论】:

    • 至于为什么它被称为“pop”而不是“pull”:我被教导关于堆叠的方式是通过与一些餐厅的弹簧加载的盘子堆叠之一进行比较。实际上,您必须按下盘子才能在顶部放更多盘子,当您拿一个时,堆栈的其余部分弹出到顶盘的位置曾是。显然这个比喻有点离题,因为在大多数实际实现中,堆栈条目本身根本不会移动——但它足以解释堆栈,而且它似乎是一个非常常用的比喻。
    【解决方案4】:

    Push/Pop 最初与 asm 中的堆栈命令有关。 push 将一个值(寄存器)放在堆栈上并更新堆栈指针,而 pop 从堆栈中获取值并减少指针。这里没有插入,这意味着存在某种偏移量。这就是为什么您还具有 push/pop _front() 和 push/pop _back() 函数的原因。它们代表了推/弹出操作的静态位置。

    【讨论】:

    • @Michael Dorgan: 你确定这些术语甚至不早于汇编语言助记符吗?毕竟,计算机科学中的大部分理论在实际计算机建成之前就已经存在。我想在任何 CPU 中实现之前就已经发明了名为“stack”的抽象数据类型(以及它的基本操作“push”和“pop”)。
    • 这是一个非常公平的陈述,可能是真的。我只是从我第一次遇到并广泛使用堆栈的想法开始。尽管如此,我们这里的主题是与计算机相关的,所以 CPU 可能是在这个问题的方案中发明的 :)
    【解决方案5】:

    至少在 C++ 中,push 和 pop 仅指像堆栈和队列这样的结构,其中操作发生的位置是数据结构中固有的。对于其他容器,例如向量和列表,我们有 push_back、push_front、pop_back 等。对于我们真的不知道项目将在哪里结束或从哪里读取它的容器,push 和 pop 不用于全部。

    【讨论】:

    • +1 我看到在 STL 队列/优先队列实现中使用了 push/pop,这是我想知道的。
    【解决方案6】:

    Push 和 Pop 只是从堆栈数据结构中插入和删除项目的操作的常规名称。任何遵循后进先出模式 (LIFO) 的操作通常称为 Push 和 Pop,但您可以随意称呼它们。

    【讨论】:

      【解决方案7】:

      pushpop 的命名可能只是为了区分可以在堆栈上执行的操作和可以在列表上执行的操作。你也可以称它们为 addremove,但它们往往暗示你可以在列表的任何位置添加或删除元素,而不是简单地在开头(或结束,如果你这么想的话)。类似地,enqueuedequeue 存在是因为 pushpop 意味着插入或删除发生在同一位置,而不是在列表的两端。

      如果您想要一个技术定义,您可能会说 pushpop 是 O(1) 操作,它们会影响 LIFO 中列表的同一端(后进先出)的方式。

      【讨论】:

        【解决方案8】:

        Push 和 pop 最初用于指代堆栈操作,但非正式地,这些术语通常用于涉及在任何线性数据结构(如堆栈、队列、数组或链接)末尾添加/删除元素的操作列表。

        【讨论】:

          【解决方案9】:

          推送只是将一个项目添加到集合的开头(或结尾)。弹出正在删除相同的项目。

          在 Java 中,List 接口有 add(0, item) 和 remove(0)。这些实际上与 push(item) 和 pop() 类似。

          但是,推送和弹出以及堆栈的特定行为很有趣,因此许多具有专门的数据结构,使推送和弹出特别有效。

          【讨论】:

            【解决方案10】:

            您要问的大部分内容都是约定俗成的。对于队列,您可以推送或入队。你会看到两者。对于堆栈,您会看到添加或推送。没有真正的硬性“规则”。如果您使用的语言使用“push”作为约定,请使用“push”。命名很重要,但只是为了可用性和常识。只需确保您的命名在单个应用程序或系统中保持一致即可。

            【讨论】:

              【解决方案11】:

              在谈论堆栈时使用名称 push 和 pop。堆栈是后进先出 (LIFO)。因此名称表明 pop 将返回最后推送的内容。

              【讨论】:

                【解决方案12】:

                直观地说,我们认为堆栈是我们可以压入值的东西,其顶部值是最后压入的东西,如果我们弹出一个我们已经压入值的堆栈,我们就有了原始堆栈。

                这种直觉可以转换为抽象的代数, 使用 Push 和 Pop 表示对称为 Stack 的数据对象的任何计算,涉及元素:

                algrebra Stack
                  {
                    data Stack;
                    data Element;
                    Empty() -> Stack;
                    Push(Stack,Element) -> Stack;
                    Pop(Stack) -> Stack;
                    Top(Stack) -> Element;
                    axiom Top(Push(s,e))==e;
                    axiom Pop(Push(s,e))==s;
                    axiom Pop(Empty())==undefined;
                 }
                

                这说明如果你能在你的系统中找到实体,

                • 您声称其中一些是堆栈类型
                • 您声称其中一些是元素,
                • 您声称是 Push 的一些功能,
                • 您声称的一些函数是 Pop、Top、Empty 等。

                那么各种函数的签名与代数中的签名匹配, 并且如果您应用各种功能,它们将表现为 公理指定。 (您选择的实体是“同构的” 到代数)。

                这种观点的优点是它没有说明 各种实体的实现,同时仍然抓住本质。 该代数涵盖了其他答案中讨论的各种工件; 应该清楚的是,用作堆栈的线性存储区域是堆栈, 使用堆栈的链表是堆栈,一端使用的双端队列是堆栈, 那一系列用作栈的磁盘块就是栈,...

                真正酷的是你可以重命名所有的数据类型和函数 在堆栈代数中,但仍然可以识别堆栈,因为重命名 对同构没有影响(因为一致的重命名只是另一种同构, 和同构组成产品同构)。任何匹配的东西 这个规范一个堆栈!

                实现中的函数名称可以是任何东西,并且 但仍然匹配,并且我们可以重命名抽象代数函数名称 任何东西,仍然匹配,允许我们按照惯例给出抽象 代数函数命名我们认为具有代表性的函数。 “推” 和“pop”是按惯例选择的。

                所以我想说,你可以称你的名字你的实现功能任何你 喜欢,但称他们为 Push 和 Pop,如果他们的行为实现了这个代数。

                因此,可以通过正式规范定义堆栈。您可以定义任何其他数据结构 也这样。

                太糟糕了,我们在记录真实代码时没有做更多的事情。

                【讨论】:

                  【解决方案13】:

                  栈的基本操作是push和pop。术语 push 用于将一些数据元素放入堆栈,而 pop 用于从堆栈中删除一些数据元素。

                  【讨论】:

                  • 提问者想要一个宽泛的定义,而不是一个例子。
                  猜你喜欢
                  • 1970-01-01
                  • 2010-09-30
                  • 2014-11-19
                  • 2016-08-16
                  • 2018-04-17
                  • 2014-01-30
                  • 1970-01-01
                  • 2022-01-17
                  • 2011-06-20
                  相关资源
                  最近更新 更多