1,链表的常规操作:
class Node(object):
"""节点类"""
def __init__(self, elem):
# _elem 存放数据元素
self.elem = elem
# _next是下一个节点的标识
self.next = None
# node = Node(100)
class SingleLinkList(object):
"""单链表类"""
def __init__(self, node=None):
self.__head = node # __代表私有变量
def is_empty(self):
"""链表是否为空"""
return self.__head == None
def length(self):
"""返回链表的长度"""
# cur 游标,用来移动遍历节点
cur = self.__head
# count 记录数量
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
"""遍历整个链表"""
cur = self.__head
while cur != None:
print(cur.elem, end=" ") # 以空格分隔,默认是换行
cur = cur.next
print("") # 换行
def add(self, item):
"""链表头部添加元素,头插法"""
node = Node(item)
node.next = self.__head
self.__head = node
# 特殊情况:原有node为空,以上语句满足该情况
def append(self, item):
"""链表尾部添加元素,尾插法"""
node = Node(item)
if self.is_empty():
self.__head = node # 链表为空的情况
else: # 链表不为空的情况
cur = self.__head
while cur.next != None:
cur = cur.next
cur.next = node
def insert(self, pos, item):
"""指定位置添加元素
:param pos 从0开始
insert(2, 100)
"""
if pos < 0: # 等同于0 的位置插入,头插法
self.add(item)
elif pos > self.length() - 1:
self.append(item)
else:
node = Node(item)
pre = self.__head
count = 0
while count < (pos - 1):
count += 1
pre = pre.next
# 当循环退出后,pre指向pos-1位置
node.next = pre.next
pre.next = node # 以上两行顺序不能变换,不然会丢掉插入数据后面的元素
# def remove(self, item):
# """删除节点方法一:2个节点pre和cur"""
# cur = self.__head
# pre = None # 两个游标
# while cur != None:
# if cur.elem == item:
# # 先判断此节点是否是头节点,
# if cur == self.__head:
# self.__head = cur.next
# else:
# pre.next = cur.next
# break # 为什么没有break 会陷入死循环啊
# else:
# pre = cur
# cur = cur.next
# 特殊情况1:空链表,退出循环,不执行任何操作,以上语句符合
# 特殊情况2:删除首节点,pre= none,原语句不行,需要考虑
# 特殊情况3:删除尾结点,以上语句符合
def remove(self, item):
"""删除节点方法二:只用一个pre节点"""
while self.__head.elem == item:
self.__head = self.__head.next
pre = self.__head
while pre.next != None:
if pre.next.elem == item:
pre.next = pre.next.next
else:
pre = pre.next
def search(self, item):
"""查找节点是否存在"""
cur = self.__head
while cur != None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
# 空链表的情况,以上语句符合
if __name__ == "__main__":
ll = SingleLinkList()
print(ll.is_empty())
print(ll.length())
ll.append(1)
print(ll.is_empty())
print(ll.length())
ll.append(2)
ll.add(8)
ll.append(3)
ll.append(4)
ll.append(5)
ll.append(6)
# 8,1,2,3,4,5,6
ll.insert(-1, 9) # 9 8 1 23456
ll.travel()
ll.insert(3, 100) # 9 8 1 100 23456
ll.travel()
ll.insert(9, 200) # 9 8 100 1 23456 200
ll.travel()
ll.append(100)
ll.travel()
ll.remove(100)
ll.travel()
# ll.remove(9)
# ll.travel()
2,移除链表——移除链表中所有值为val的元素
- 题目链接:203. 移除链表元素 - 力扣(LeetCode)
- 主要思路:虚拟头节点:因为暴力解法需要把头结点单独考虑,为了同意删除规则,设置虚拟头节点
- 难点和易错点:
- 删除节点操作:找到删除元素的前一个节点,pre.next = pre.next.next
- 需要考虑特殊情况:删除的是头节点
方法一:原链表删除元素:分两种情况删除,头节点和非头节点的删除方式不同
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
while head != None and head.val == val:
head = head.next
pre = head
while pre and pre.next:
if pre.next.val == val:
pre.next = pre.next.next
else:
pre = pre.next
return head
方法二:虚拟头节点:统一规则删除
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional [ListNode]:
# 创建虚拟头节点
dummy_head = ListNode(next = head)
# 遍历列表并删除值为val的节点
current = dummy_head
while current.next:
if current.next.val == val:
current.next = current.next.next
else:
current = current.next
return dummy_head.next
3,设计链表——同1,常规操作
- 题目链接:707. 设计链表 - 力扣(LeetCode)
- 思路:链表的常规操作
- 难点和易错点:
- 增加节点操作:2步:顺序不能对调,不然的话会丢失后面的元素
- node.next = cur.next
- cur.next = node
class MyLinkedList:
def __init__(self):
self.dummy_head = ListNode()
self.size = 0
def get(self, index: int) -> int:
if index < 0 or index >= self.size:
return -1
current = self.dummy_head.next
for i in range(index):
current = current.next
return current.val
def addAtHead(self, val: int) -> None:
self.dummy_head.next = ListNode(val, self.dummy_head.next)
self.size += 1
def addAtTail(self, val: int) -> None:
current = self.dummy_head
while current.next:
current = current.next
current.next = ListNode(val)
self.size += 1
def addAtIndex(self, index: int, val: int) -> None:
if index < 0 or index > self.size:
return
current = self.dummy_head
for i in range(index):
current = current.next
current.next = ListNode(val, current.next)
self.size += 1
def deleteAtIndex(self, index: int) -> None:
if index < 0 or index >= self.size:
return
current = self.dummy_head
for i in range(index):
current = current.next
current.next = current.next.next
self.size -= 1
# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)
4,反转链表——递归的方法还不会
- 题目链接:206. 反转链表 - 力扣(LeetCode)
- 思路:方法一:双指针;方法二:递归( 目前还不会)
- 难点和易错点:更新指针的顺序不能反了: pre = cur;cur = temp
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur = head
pre = None
while cur != None:
temp = cur.next # 1,保存原来cur的下一个元素
cur.next = pre # 2,翻转
pre = cur # 3,往下移动,更新pre和cur指针
cur = temp
return pre