- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
基于数组vs链接实现Stack的优缺点是什么?据我所知,我认为链接永远是实现Stack的更好方法,因为:
1)不需要随机访问。
2)数组效率低下,因为它们必须调整大小(浪费时间),而且存储效率低下(总是浪费一些空间)
我确定我在这里错过了一些东西,因为:
1)java.util.Stack是基于数组实现的(它是java.util.Vector的子类,它是Java集合接口创建之前的旧类,实际上类似于ArrayList)。因此,java的创建者选择执行基于数组的实现。
2)我已经阅读了关于stackoverflow的答案here,“另一方面,基于数组的实现可能具有更好的运行时行为”。这是什么意思,尽管我不知道。
我正在寻找的比较应该包括以下参数:
1)理论时间和存储要求。
2)运行时性能(如果与理论比较有所不同)。
请包括由于我缺乏知识而未能提及的任何其他重要参数。我使用java,如果在结论上有任何不同的话。
附言:我无法在本网站上的任何其他答案中找到该问题的所有要点,因此仅在我的所有问题均已正确回答且在另一问题中足够详细时,才将此问题标记为重复。
PPS-我知道这是一个很长的问题,因此TIA需要您努力:)另外,如果您觉得它太宽泛,请在将其标记为“太宽泛”之前对如何分解加以评论,以便我可以根据需要对其进行编辑。
最佳答案
首先,您应该意识到java.util.Stack
是一个“遗留集合”,可以追溯到Java 1.0。它扩展了java.util.Vector
的确是基于数组的。但是,这通常被认为是不良的对象设计。这并不意味着基于数组的堆栈是一件坏事,但是您应该意识到,仅因为JDK中包含某些内容并不意味着它是一个好主意。对于较旧的API尤其如此。java.util.ArrayDeque
是更现代的类似于堆栈的数据结构。它也是基于数组的。它还有很多其他功能,但是如果坚持使用push
和pop
方法(相当于addFirst
和removeFirst
),则基本上是堆栈。请注意,在其文档中说:
当用作堆栈时,此类可能比Stack
更快。
如果您看一下实现,则Stack
与Vector
一样,是同步的,因此会使其速度变慢。 Stack
的push
和pop
方法是根据Vector
方法实现的,这些方法也是同步的。这意味着附加的方法调用以及嵌套的同步。 (不过,JIT可能可以优化其中的大多数功能。)相反,ArrayDeque
是不同步的,其类似堆栈的方法使用直接在其内部数组上进行操作的简单操作。请注意,在这里我没有做任何基准测试来验证文档的声明。
无论如何,ArrayDeque
是首选的Java集合,用于需要类似堆栈行为的问题。
但是您在问的是链接数据结构,而不是基于数组的数据结构。让我们将ArrayDeque
与另一个Java链接数据结构LinkedList
进行比较。这实现了Deque
,因此它也可以用作堆栈。你说,
1)不需要随机访问。
真正。请注意,即使ArrayDeque
基于数组,也不提供随机访问。两者都没有优势。
2)数组效率低下,因为它们必须调整大小(浪费时间),并且它们使用存储效率低下(总是浪费一些空间)
任何数据结构都会有效率低下的情况。但是,不同的数据结构将具有不同的权衡。如果ArrayDeque
的数组的大小不适合堆栈的典型容量,则必须重新调整大小。但是,一旦阵列足够大,就不需要连续调整大小。如果堆栈缩小,则阵列仍将占用空的空间。可以将其视为浪费,也可以将其视为保留内存,以便在堆栈再次增长时不必调整大小和复制内存。
比较情况与LinkedList
。在内部,每个列表元素都需要一个Node
实例。 (请参见源here。)每个实例包含三个引用:一个引用到数据元素,一个引用到下一个Node
,以及一个引用到前一个Node
。假设具有压缩指针的64位JVM,则每个引用32位。每个对象都有一个包含64位标记字和32位类指针的标头。这样一来,总共有六个32位字,即每个列表元素24个字节。六个词中只有一个是“有效负载”(即元素本身),因此每个元素20个字节或83%的开销!
相比之下,数组中的每个其他元素仅占用用于引用该元素的空间,即32位。
例如,在LinkedList
中存储1,000个元素会消耗大约24K的内存,但是在ArrayDeque
中存储它们只会消耗大约4K的内存。即使该数组的大小是容纳1000个元素所需的两倍,也只有8K,仍然只是LinkedList
大小的一小部分。
“另一方面,基于数组的实现可能具有更好的运行时行为”
这可能是指遍历链表比遍历数组要慢。有两个原因。首先,链接节点占用更多的内存,因此必须读取更多的内存才能获得相同的信息。每个节点24字节时,典型的64字节高速缓存行可以容纳2.67个节点。其次,链接节点可能会在内存中随机分布一些,因此平均而言,每条缓存行的节点数可能少于该节点。结果是,遍历链接列表将导致大量缓存丢失,因为引用的本地性很差。
另一方面,由于数组中的引用被密集打包而没有任何开销,因此16个数组元素可以容纳在单个64字节高速缓存行中。遍历数组将导致更少的缓存未命中。此外,内存子系统针对顺序访问进行了优化,因此它们可能能够预取下一个缓存行,从而进一步减少内存开销。
考虑到内存消耗和内存访问的性能成本,通常首选基于数组的结构。在某些情况下,链接结构的性能更好,但似乎比大多数人想象的要少。
除了性能,与栈的数组结构相比,链接结构有一个明显的优势:不变的持久性。在基于数组的堆栈上压入和弹出元素会固有地使数组变异,因此以前的版本不再存在。在链接结构上推入和弹出节点不需要更改任何链接节点,因此即使其他人在该堆栈上推入和弹出元素,对堆栈过去状态的引用也可以持久保存,并且将保持不变。实际上,它们是不同的堆栈,具有共享的公共部分。这在函数式编程环境中非常有用。
关于java - 堆栈ADT(抽象数据类型)实现-数组与链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33780618/
我对 java 中的抽象有点困惑。 我查了很多页面说抽象就是数据隐藏(隐藏实现)。 我对抽象的理解是它是“部分实现”。只需在抽象类/接口(interface)中定义您需要的内容,然后扩展/实现它们并添
我是 Ruby 的新手,主要来自 C# 和 ActionScript 3(以及其他语言)。我对抽象功能很好奇。具体来说,包装和抽象 Ruby 的 FTP 和 SFTP 库。 我四处搜索,发现了一个名为
目录 Java基础知识(抽象) 抽象 抽象定义 abstract的使用 定义抽象类
这个月我花了一些时间与 Emacs Lisp 进行斗争,试图获得更好地满足我需求的自动缩进。令人惊讶的是,大多数缩进代码是多么低级。我只看到了很少的抽象,例如 搜索不在字符串或注释中的第一个正则表达式
我有以下内容: public abstract class Foo{ //contents of Foo // ... public class Bar extends
我有三个类(class)(A 类、B 类和 C 类)。 类 A 调用 B 的实例并运行 start()。 B类扩展了Thread,因此当调用start()时,run()方法中的任何内容都会被执行。 在
这个问题已经有答案了: Calling a subclass method from superclass (5 个回答) 已关闭 7 年前。 Klasse1是一个抽象类,有一个 foo()方法。 K
我有一个这样的函数: def test(): x = "3" # In actual code, this is computed if x is None: retu
我有两个基类之间的关系: public abstract class RecruiterBase { // Properties declare here // Constructors de
这是我第一次发帖,但我遇到了很多问题。我目前有一个带有标题的 AbstractDevice 类: public abstract class AbstractDevice> implements De
我有一个 MotorDefinition 类和一个名为 Motor 的抽象类: class MotorDefinition { public: MotorDefinition(int p1,
是否有任何方法可以在这种代码(sass)中制定 css 的抽象规则: #cottage-image-gallery input:nth-of-type(1):checked ~ label:nth-o
是否可以声明一个已知的基类型并允许传输所有派生类型? [ServiceContract] public interface IService { [OperationContract]
我目前正在为基于 Java 的文本游戏开发角色生成机制,但我遇到了一个问题,看不出哪里出了问题。我有一个“Character”类,它是抽象的,然后是另一个类“NPCharacter”,它是建立在这个之
抱歉,标题令人困惑。不太确定如何表达它,这可能是问题所在! 我正在寻找一个好的抽象来用于涉及并发线程的情况。 我已经接近了,但还不是很清楚。 稍微简化一下,我在 Android 手机上收集了两种传感器
提前感谢您阅读本文。我不完全理解如何/何时使用摘要,所以我试图在我从事的每个项目中考虑它,看看它是否会在某一天全部点击 Smile | :) 此外,可访问性级别(私有(private)、 protec
我正在探索用于生成 Web 内容的 XML -> XSLT -> HTML 模因。我的 XSLT 经验很少。 我很好奇 XSLT 中有哪些机制可用于处理抽象或“重构”。 例如,使用通用 HTML 和服
在这些谈话中 Nicholas Zakas和 Addy Osmani他们讨论了在构建大型 Javascript 应用程序时将外观模式用作沙箱的想法,以便将应用程序与底层基础库分离。 这种解耦理论上允许
我使用C++和CUDA/C,想为特定问题编写代码,但遇到了一个非常棘手的简化问题。 我在并行编程方面的经验不容忽视,但相当有限,我无法完全预见到此问题的特殊性。 我怀疑是否有一种方便甚至“轻松”的方式
假设我有: trait A class B extends A class C extends A 有没有办法配置类型参数: class Foo[AType <: A with canCreateIn
我是一名优秀的程序员,十分优秀!