链表

文摘   2024-09-10 20:19   吉林  

链表

在计算机科学中, 一个 链表 是数据元素的线性集合, 元素的线性顺序不是由它们在内存中的物理位置给出的。相反, 每个元素指向下一个元素。它是由一组节点组成的数据结构,这些节点一起,表示序列。

链表是一种基础的数据结构,它由一系列节点组成,这些节点通过指针连接起来。

每个节点至少包含两个部分:一部分是存储数据的元素,另一部分是指向列表中下一个节点的指针(在双向链表中,还会有一个指向前一个节点的指针)。

链表允许动态地在任何位置添加或删除节点,这使得它在处理未知数量的数据时非常有用。

单向链表(Singly Linked List):

每个节点包含一个指向下一个节点的指针。

插入和删除操作通常在链表的末尾或通过一个给定的节点进行。

双向链表(Doubly Linked List):

每个节点包含两个指针,一个指向前一个节点,另一个指向下一个节点。

这使得可以在两个方向上遍历链表,也便于在节点的任意一侧进行插入和删除。

循环链表(Circular Linked List):

链表的最后一个节点的指针指向链表的第一个节点(单向循环链表)或最后一个节点(双向循环链表)。

循环链表常用于实现队列和栈等数据结构。

优点:

动态大小:链表的大小可以根据需要动态增长或缩小。

插入和删除操作高效:在已知节点的情况下,可以在O(1)时间内插入或删除节点。

无需连续内存:链表不需要一块连续的内存空间,可以更好地利用内存。

缺点:

访问速度慢:访问链表中的元素需要从头开始遍历,时间复杂度为O(n)。

额外的内存开销:每个节点需要额外的空间来存储指针。

链表的应用

实现栈和队列。

用于哈希表中的冲突解决。

用于实现某些类型的数据库和文件系统。

在最简单的形式下,每个节点由数据和到序列中下一个节点的引用(换句话说,链接)组成。这种结构允许在迭代期间有效地从序列中的任何位置插入或删除元素。

更复杂的变体添加额外的链接,允许有效地插入或删除任意元素引用。链表的一个缺点是访问时间是线性的(而且难以管道化)。

更快的访问,如随机访问,是不可行的。与链表相比,数组具有更好的缓存位置。

基本操作的伪代码

插入

add

Add(value)
  Pre: value is the value to add to the list
  Post:  value has been placed at the tail of the list
  n ← node(value)
  if head = ø
    head ← n
    tail ← n
  else
    tail.next ← n
    tail ← n
  end if
end Add

Prepend

Prepend(value)
 Pre: value is the value to add to the list
 Post: value has been placed at the head of the list
 n ← node(value)
 n.next ← head
 head ← n
 if tail = ø
   tail ← n
 end
end Prepend

搜索

Contains

Contains(head, value)
  Pre: head is the head node in the list
       value is the value to search for
  Post: the item is either in the linked list, true; otherwise false
  n ← head
  while n != ø and n.value != value
    n ← n.next
  end while
  if n = ø
    return false
  end if
  return true
end Contains

删除

Remove

Remove(head, value)
  Pre: head is the head node in the list
       value is the value to remove from the list
  Post: value is removed from the list, true, otherwise false
  if head = ø
    return false
  end if
  n ← head
  if n.value = value
    if head = tail
      head ← ø
      tail ← ø
    else
      head ← head.next
    end if
    return true
  end if
  while n.next != ø and n.next.value != value
    n ← n.next
  end while
  if n.next != ø
    if n.next = tail
      tail ← n
    end if
    n.next ← n.next.next
    return true
  end if
  return false
end Remove

遍历

Traverse

Traverse(head)
  Pre: head is the head node in the list
  Post: the items in the list have been traversed
  n ← head
  while n != ø
    yield n.value
    n ← n.next
  end while
end Traverse

反向遍历

ReverseTraversal

ReverseTraversal(head, tail)
  Pre: head and tail belong to the same list
  Post: the items in the list have been traversed in reverse order
  if tail != ø
    curr ← tail
    while curr != head
      prev ← head
      while prev.next != curr
        prev ← prev.next
      end while
      yield curr.value
      curr ← prev
    end while
   yield curr.value
  end if
end ReverseTraversal

复杂度

时间复杂度

AccessSearchInsertionDeletion
O(n)O(n)O(1)O(1)

空间复杂度

O(n)

https://gitee.com/lucky_ck/algorithms

我希望这篇文章对您有所帮助。

Thank you for reading.

推荐阅读


全栈开发ck
叩首问路,码梦为生