定义:链表(Linked List):一种线性存储结构。它使用一组任意的存储单元(可以是连续的或不连续的),来存储一组具有相同类型的数据
链表,是实现线性表的链式存储结构的基础
存储方式
由上图可知,链表中的每一个数据都存储在一个链节点中,而为了是每个链节点连接起来,还需要存放一个指出这个数据元素在逻辑关系上的直接后继元素所在链节点地址,该地址被称为后继指针next
链式存储的优缺点:
双向链表(Doubly Linked List):也叫双链表。与一般链表不同的是这里的每个链节点中有两个指针,分别指向直接前驱与直接后继
达到的效果:使得从任意一个结点开始都可以很方便地访问它的前驱与后继
链表是由链节点通过 next 链接而构成。所以,链表的结构定义分为两步:
定义链节点类(ListNode):LIstNode类使用成员变量val来表示数据元素的值,使用指针变量next表示后继指针
定义链表类(LinkedList):LinkedList类中只有一个链节点变量head来表示链表的头节点
代码实现:
# 链节点类
class LinkNode:
def __ init__(self, val = 0, next = None):
self.val = val
self.next = next
# 链表类
class LinkedList:
def __init__(self):
self.head = None
# 根据一个data初始化一个新链表
def create(self, data):
self.head() = ListNode(0)
# 此时指针指向链表的开头
cur = self.head
for i in range(len(data)):
node = ListNode(data[i])
# 每添加一个数据cur就往后移动一下
cur.next = node
cur = cur.next
# 获取链表长度
def length(self):
count = 0
cur = self.head
while cur:
count += 1
cur = cur.next
return count
# 查找元素
def find(self, val)
cur = self.head
while cur:
if cur.val == val:
return cur
cur = cur.next
return None
按照插入位置的不同,将插入操作分为三种
链表头部插入元素:在链表第 1 个链节点之前插入值为 val 的链节点
# 头部插入元素
def insertFront(self, val):
node = ListNode(val)
node.next = self.head
self.head = node
链表尾部插入元素:在链表最后 1 个链节点之后插入值为 val 的链节点
在链表的第index个位置插入元素
步骤:
时间复杂度:O(n)
代码实现:
# 在链表的index位置插入数据
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 的链节点
# 在链表的末尾插入元素
def insertRear(self, val):
node = ListNode(val)
cur = self.head
while cur.next:
cur = cur.next
cur.next = node
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
与插入元素相同,根据删除元素的所在位置将删除元素分为三种情况
链表头部删除元素
# 删除链表头部元素
def removeFront(self):
if self.head:
self.head = self.head.next
链表中间删除元素
# 删除链表第index个元素
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
链表尾部删除元素
# 删除链表尾部元素
def removeRear(self):
if not self.head.next:
return 'Error'
cur = self.head
while cur.next.next:
cur = cur.next
cur.next = None
# 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: ListNode) -> ListNode:
prev, cur = None, head
while cur is not None:
next = cur.next
cur.next = prev
prev = cur
cur = next
return prev
class Solution:
def removeElements(self, head: ListNode, val: int) -> ListNode:
if head == None:
return head
while head != None and head.val == val:
head = head.next
if head == None:
return head
cur, cur_next = head, head.next
while cur_next != None:
if cur_next.val == val:
while cur_next != None and cur_next.val == val:
cur_next = cur_next.next
cur.next = cur_next
else:
cur = cur_next
cur_next = cur_next.next
return head
class Solution:
def oddEvenList(self, head: ListNode) -> ListNode:
if not head:
return head
evenHead = head.next
odd, even = head, evenHead
while even and even.next:
odd.next = even.next
odd = odd.next
even.next = odd.next
even = even.next
odd.next = evenHead
return head
思路
相关复杂度:
代码实现:
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
if head is None:
return True
# 找到前半部分链表的尾节点并反转后半部分链表
first_half_end = self.end_of_first_half(head)
second_half_start = self.reverse_list(first_half_end.next)
# 判断是否回文
result = True
first_position = head
second_position = second_half_start
while result and second_position is not None:
if first_position.val != second_position.val:
result = False
first_position = first_position.next
second_position = second_position.next
# 还原链表并返回结果
first_half_end.next = self.reverse_list(second_half_start)
return result
def end_of_first_half(self, head):
fast = head
slow = head
while fast.next is not None and fast.next.next is not None:
fast = fast.next.next
slow = slow.next
return slow
def reverse_list(self, head):
previous = None
current = head
while current is not None:
next_node = current.next
current.next = previous
previous = current
current = next_node
return previous