单链表插入和删除的时间复杂度
Time complexity of Single Link List Insertion and deletion
我对链表的时间复杂度有点困惑。在本文中,它指出在链表中插入和删除是O(1)。我想知道这怎么可能?是否假设前进指针和下一步指针是已知的?这不是双链表吗?如果有人能澄清一下,我会很感激的。单链表的插入/删除的时间复杂度如何为O(1) ?
是否假设前进指针和下一指针是已知的?
在单链表中,对于插入和删除,都需要在插入/删除点之前有一个指向元素的指针。那么一切都解决了。
例如:# insert y after x in O(1)
def insert_after(x, y):
y.next = x.next
x.next = y
# delete the element after x in O(1)
def delete_after(x):
x.next = x.next.next
对于许多应用程序,很容易通过算法携带当前正在查看的项的前身,以允许在恒定时间内动态插入和删除。当然,你总是可以在O(1)的列表前面插入和删除,这允许类似堆栈(LIFO)的使用模式。
当你只知道一个项的指针时,删除一个项在O(1)中通常不可能。EDIT:如codebeard所示,我们可以通过知道插入/删除点的指针来插入和删除。它涉及到从后继程序复制数据,从而避免修复前一个程序的next
指针。
是的,这是假设您已经知道要插入数据的位置。
假设列表中有一些项目p
,并且您想在列表中的p
之后插入一个新元素new
:
new->next = p->next;
p->next = new;
或者,假设您想在 p
之前插入new
。这仍然可以在O(1)时间内完成:
if (p == head) {
new->next = head;
head = new;
} else {
tmp = p->data;
p->data = new->data;
new->data = tmp;
new->next = p->next;
p->next = new;
}
对于在传统的单链表中删除项,它不是严格的O(1)!
删除除最后一个元素以外的任何元素都是0(1)。如果你试图删除单链表中的最后一个元素,你需要知道它之前的元素(假设你之前不知道它,这需要O(N)时间)。
删除p
:
free_if_necessary(p->data);
if (p->next) {
/* O(1) */
nextnext = p->next->next;
nextdata = p->next->data;
destroy_if_necessary(p->next);
p->data = nextdata;
p->next = nextnext;
} else if (p == head) {
destroy_if_necessary(p);
head = NULL;
} else {
/* O(n) */
prev = find_prev(head, p);
destroy_if_necessary(p);
prev->next = NULL;
}
这可能与数组的删除和插入操作有关。
有一个先决条件是你知道在哪里插入或删除。
在数组中,当要插入或删除位置为pos
的元素时,需要将其他元素移动到位置pos
之后,因此复杂度为O(N)
。
但是在List中,当你做同样的操作时,你不需要考虑其他元素,所以复杂度是O(1)
相关文章:
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- while循环中while循环的时间复杂度是多少
- 我可以创建一个包含两个变量的 for 循环,但时间复杂度仍然为 O(n) 吗?
- 函数的时间复杂度是多少?
- 如何检查两个 std::向量在小于 O(n) 的时间复杂度内是否相等
- 时间复杂度 当具有复合数据类型(如元组或对)时?
- 如何计算此排序函数的时间复杂度?
- 计算两个代码块的时间复杂度
- C++ 中具有 O(1) 搜索时间复杂度的数据结构
- 具有嵌套 if-else 的循环的时间复杂度
- 将树节点添加到向量向量中的 n 元树遍历的平均和最坏情况时间复杂度是多少?
- 如何计算函数的时间复杂度?
- 求解包含"variables"的 T(n) 时间复杂度
- 查找数字是否为 2 的幂的时间复杂度
- C++ - 最坏情况和平均情况插入时间复杂度在 std::unordered_map <int,int>?
- 为什么一种算法在相同的时间复杂度下比另一种算法更快?
- 关于记忆后这种递归关系的时间复杂度
- 2 个嵌套循环的时间复杂度
- 给定C++代码的时间复杂度是多少?
- 单链表插入和删除的时间复杂度