跟着datawhale刷力扣,以下基本来自于其文档,感谢
链表(Linked List):一种线性表数据结构。它使用一组任意的存储单元(可以是连续的,也可以是不连续的),来存储一组具有相同类型的数据。即「链表」 是实现线性表的链式存储结构的基础。
单链表每个数据元素占用若干存储单元的组合称为一个「链节点」,还要存放一个指出这个数据元素在逻辑关系上的直接后继元素所在链节点的地址,该地址被称为「后继指针 next」。
双向链表(Doubly Linked List):链表的一种,也叫做双链表。它的每个链节点中有两个指针,分别指向直接后继和直接前驱。
循环链表(Circular linked list):链表的一种。它的最后一个链节点指向头节点,形成一个环。
链表是由链节点通过 next
链接而构成的,所以先来定义一个简单的链节点类,即 ListNode
类。ListNode
类使用成员变量 val
表示数据元素的值,使用指针变量 next
表示后继指针。
然后再定义链表类,即 LinkedList
类。ListkedList
类中只有一个链节点变量 head
用来表示链表的头节点。
# 链节点类
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
# 链表类
class LinkedList:
def __init__(self):
self.head = None
建立一个线性链表的过程是:根据线性表的数据元素动态生成链节点,并依次将其连接到链表中。其做法如下:
1
个数据元素开始依次获取表中的数据元素。1
个链节点的地址。# 根据 data 初始化一个新链表
def create(self, data):
self.head = ListNode(0)
cur = self.head
for i in range(len(data)):
node = ListNode(data[i])
cur.next = node
cur = cur.next
线性链表的长度被定义为链表中包含的链节点的个数。求线性链表的长度操作只需要使用一个可以顺着链表指针移动的指针变量 cur
和一个计数器 count
。具体做法如下:
cur
指向链表的第 1
个链节点。next
指针遍历链表,指针变量 cur
每指向一个链节点,计数器就做一次计数。cur
指向为空时结束遍历,此时计数器的数值就是链表的长度,将其返回即可。n
,基本操作是 cur
指针的移动,操作的次数为 n,因此算法的时间复杂度为 O ( n ) O(n) O(n)。# 获取链表长度
def length(self):
count = 0
cur = self.head
while cur:
count += 1
cur = cur.next
return count
在链表中查找值为 val
的位置:链表不能像数组那样进行随机访问,只能从头节点 head
开始,沿着链表一个一个节点逐一进行查找。如果查找成功,返回被查找节点的地址。否则返回 None
。
查找元素操作的问题规模是链表的长度 n
,而基本操作是指针 cur
的移动操作。
链表中插入元素操作分为三种:
1
个链节点之前插入值为 val
的链节点。1
个链节点之后插入值为 val
的链节点。i
个链节点之前插入值为 val
的链节点。算法实现的步骤为:
# 头部插入元素
def insertFront(self, val):
node = ListNode(val)
node.next = self.head
self.head = node
算法实现的步骤为:
val
的链节点 node
。cur
指向链表的头节点 head
。next
指针移动 cur
指针,从而遍历链表,直到 cur.next == None
。cur.next
指向将新的链节点 node
。# 尾部插入元素
def insertRear(self, val):
node = ListNode(val)
cur = self.head
while cur.next:
cur = cur.next
cur.next = node
算法的实现步骤如下:
cur
和一个计数器 count
。令 cur
指向链表的头节点,count
初始值赋值为 0
。next
指针遍历链表,指针变量 cur
每指向一个链节点,计数器就做一次计数。count == index - 1
时,说明遍历到了第 index - 1
个链节点,此时停止遍历。val
的链节点 node
。node.next
指向 cur.next
。cur.next
指向 node
。# 中间插入元素
def insertInside(self, index, val):
count = 0
cur = self.head
while cur and count < index - 1:
count += 1
cur = cur.next
if not cur:
return 'Error'
node = ListNode(val)
node.next = cur.next
cur.next = node
将链表中第 i
个元素值改为 val
:首先要先遍历到第 i
个链节点,然后直接更改第 i
个链节点的元素值。具体做法如下:
cur
和一个计数器 count
。令 cur
指向链表的头节点,count
初始值赋值为 0
。next
指针遍历链表,指针变量 cur
每指向一个链节点,计数器就做一次计数。count == index
时,说明遍历到了第 index
个链节点,此时停止遍历。cur
的值 val
。# 改变元素
def change(self, index, val):
count = 0
cur = self.head
while cur and count < index:
count += 1
cur = cur.next
if not cur:
return 'Error'
cur.val = val
链表的删除元素操作同样分为三种情况:
1
个链节点。1
个链节点。i
个链节点。直接将 self.head
沿着 next
指针向右移动一步即可。
# 链表头部删除元素
def removeFront(self):
if self.head:
self.head = self.head.next
删除链表中第 i
个元素的算法具体步骤如下:
先使用指针变量 cur
移动到第 i - 1
个位置的链节点。
然后将 cur
的 next
指针,指向要第 i
个元素的下一个节点即可。
# 链表中间删除元素
def removeInside(self, index):
count = 0
cur = self.head
while cur.next and count < index - 1:
count += 1
cur = cur.next
if not cur:
return 'Error'
del_node = cur.next
cur.next = del_node.next