Data structures 大O表示法数组与链表插入

Data structures 大O表示法数组与链表插入,data-structures,big-o,Data Structures,Big O,大O表示法数组与链表插入: 根据关于数组的学术文献,它是常数O(1),而对于链表,它是线性O(n) 一个数组只接受一次乘法和加法 未在连续内存中列出的链表需要遍历 这个问题是,O(1)和O(n)是否分别准确地描述了数组和链表的索引/搜索成本?我认为数组的插入速度较慢。当然,您必须迭代链表,但您必须分配、保存和释放内存才能插入到数组中。假设您谈论的是一个已经知道插入点的插入,也就是说,这不考虑遍历列表以找到正确位置: 数组中的插入取决于插入位置,因为需要移动现有值。最坏的情况(插入数组[0])是O

大O表示法数组与链表插入:

根据关于数组的学术文献,它是常数O(1),而对于链表,它是线性O(n)

一个数组只接受一次乘法和加法

未在连续内存中列出的链表需要遍历


这个问题是,O(1)和O(n)是否分别准确地描述了数组和链表的索引/搜索成本?

我认为数组的插入速度较慢。当然,您必须迭代链表,但您必须分配、保存和释放内存才能插入到数组中。

假设您谈论的是一个已经知道插入点的插入,也就是说,这不考虑遍历列表以找到正确位置:

数组中的插入取决于插入位置,因为需要移动现有值。最坏的情况(插入数组[0])是O(x)


在列表中插入是O(1),因为您只需要修改相邻项目的下一个/上一个指针。

您引用的文献是什么?数组的大小是在创建数组时确定的,以后不会更改。插入实际上只能在阵列末端的空闲插槽上进行。任何其他类型的插入都可能需要调整大小,这当然不是
O(1)
。链表的大小取决于实现,但必须始终足够大以存储其所有元素。元素可以插入列表中的任何位置,找到合适的索引需要遍历。

O(1)
准确地描述了在数组末尾插入。但是,如果要插入到数组的中间,则必须将所有元素移到该元素之后,因此在这种情况下插入数组的复杂性为
O(n)
。如果数组已满,则必须调整数组大小,结束追加也会减少这种情况

对于链表,您必须遍历列表以进行中间插入,这就是
O(n)
。不过,您不必向下移动元素

维基百科上有一个很好的图表:


很久以前,在一个内存比磁盘空间大的系统上,我实现了一个索引链表,它在手工输入或从磁盘加载时被索引。每个记录都被追加到内存中的下一个索引中,磁盘文件打开了追加到末尾的记录

在I型无线电棚屋计算机上进行的程序出纳式拍卖销售和磁盘写入仅是电源故障和存档记录的保险,因为为了满足时间限制,必须从RAM中取出数据,并按相反顺序打印,这样买家就可以问起第一个出现的物品是否是最后一个他看到的物品购买。每个买家和卖家都链接到他们销售的最后一个项目,并且该项目链接到之前的项目。它只是一个从下到上遍历的单个链接列表

通过反向条目进行了更正。我在几件事情上使用了相同的方法,如果该方法适用于手头的工作,并且索引保存到磁盘,并且不必像断电时那样将文件重新加载到内存中,那么我从未找到一个更快的系统

后来我写了一个程序,以更常规的方式进行编辑。它还可以重新组织数据以便将其分组。

tldr未排序的数组类似于集合。与集合一样,元素可以被添加、删除、迭代和读取。但是,与集合一样,谈论在特定位置插入元素是没有意义的,因为这样做将试图对定义为未排序的内容施加排序顺序


根据关于数组的学术文献,它是常数O(1),而对于链表,它是线性O(n)

值得理解的是,为什么学术文献将数组insert引用为数组的O(1)。有几个概念需要理解:

  • 数组定义为未排序(除非另有明确说明)

  • 数组的长度(定义为数组包含的元素数)可以在O(1)时间内任意增加或减少,并且数组的最大大小没有限制

    (在真实的计算机中,情况并非如此,原因是各种因素,如内存大小、虚拟内存、交换空间等。但就算法而言,这些因素并不重要-我们关心的是,随着输入大小朝无穷大的方向增加,算法的运行时间如何变化,而不是它在具有p内存大小和操作系统。)

  • 插入和为O(1),因为数组是未排序的数据结构

  • 插入不是赋值

考虑将元素添加到未排序的数据结构中的实际含义。由于没有定义的排序顺序,因此实际发生的任何顺序都是任意的,并不重要。如果从面向对象API的角度考虑,方法签名将类似于:

Array.insert(Element e)
请注意,这与其他数据结构(如链表或排序数组)的插入方法相同:

LinkedList.insert(Element e)
SortedArray.insert(Element e)
在所有这些情况下,insert方法的调用者都没有指定要插入的值最终存储的位置—这是数据结构的内部细节。此外,调用者尝试在数据结构中的特定位置插入元素—无论是对于已排序的还是未排序的数据结构—也没有任何意义。Fo对于一个(未排序的)链表,根据定义,该列表是未排序的,因此排序顺序是不相关的。对于已排序的数组,根据定义,插入操作将在数组的特定点插入元素

因此,将数组插入操作定义为:

Array.insert(Element e, Index p)
Array.insert(Element e, Index p)
array[0] = 10
array[1] = 20
Array.insert(v):    
    array.length = array.length + 1
    // in standard algorithmic notation, arrays are defined from 1..n not 0..n-1
    array[array.length] = v