单个 link 列表中的时间复杂度

Time Complexity in singly link list

我正在研究数据结构:单link列表。

网站说单linked列表的插入和删除时间复杂度为O(1)。我错过了什么吗?

website link

我用 C++ 做这个,我只有一个 root pointer。如果我想在最后插入,那么我必须一直走到后面,也就是O(n)

对此的解释是,linked table中的大O符号指的是函数实现本身,不包括遍历列表以查找列表中的前一个引用节点.

如果您按照 link 到 Singly-LinkedList implementation 的维基百科文章,它会变得更清楚:

function insertAfter(Node node, Node newNode)
function removeAfter(Node node)     

以上函数签名已经将前导节点作为参数(隐含地与其他变体相同)。

寻找前驱是一个不同的操作,可能是 O(n) 或其他时间复杂度。

您在两个地方错过了界面:

  1. std::list::insert()/std:list::erase() 需要一个指向要插入或擦除的元素的迭代器。这意味着您没有搜索,而只是更改列表中元素中的两个指针,这是恒定的复杂性。

  2. 可以通过 push_back 在列表末尾插入。该标准要求这也是 O(1)。这意味着,如果您有 std::list,它将存储第一个和最后一个元素。

编辑:抱歉,您遇到了 std::forward_list。即使名称为 insert_after 和 erase_after,第 1 点也适用于此。点2不行,你要迭代到列表末尾。

I do this in C++, and I only have a root pointer. If I want to insert at the end, then I have to travel all the way to the back, which means O(n).

这是两个操作,您首先 搜索 O(n) 给定位置的列表,然后 将 O(1) 元素插入列表。

在单链表中,插入操作包括:

  • 前一个元素的交替指针

  • 将对象包装到数据结构中并将其指针设置为下一个元素

两者都不受列表大小的影响。

另一方面,以结构为例。每个元素的插入都需要 O(log(n)) 操作才能保留其结构。树结构具有类似的机制,在插入时将 运行 并取决于当前树的大小。

这里认为你已经有了节点,之后你需要添加一个新的元素

在这种情况下,单链表的插入时间复杂度变为 O(1)。

事实是,与 array 不同,我们不需要在插入时移动 singly-linked list 的元素。因此,一个singly-linked列表的插入时间复杂度是O(1).

假设您有一个 Python list 填充整数...

my_list = [9, 8, 4, 5, 6]

... 并且您想在元素 8 之后插入数字 3

my_list.insert(2, 3)

打印结果为:

[9, 8, 3, 4, 5, 6]

当你对my_list进行插入时,元素3之后的其他元素都向右移动,因此它们的索引也发生了变化。因此,在给定索引处插入元素的时间复杂度为 O(n).

但是singly-linked lists里面没有数组元素,但是chained nodesnode values.

Image source: LeetCode

如上图所示,next节点的prev节点holds the reference。正如@πìντα ῥεῖ 所说,“函数签名已经将前导节点作为参数”。你可以在O(n)时间找到前一个节点,但是在插入一个新节点时,你只需要改变连接节点的地址,即O(1)时间复杂度。