本文是学习陆老师的《python全栈工程师 - 数据结构与算法》课程的笔记,欢迎学习交流。同时感谢陆老师的精彩传授!
文末附有本节课单链表操作全部代码
一、课程目标
- 链表数据的结构
- 链表结构的python实现
- 链表的操作时间复杂度
二、详情解读
01.链表结构:
链表就好像链条一样,一节就是一个数据节点。
链表特点:
- 1、每一个数据节点包括数据本身以及前后节点位置(单链表只包含下一节点位置)
- 2、链表不需要连续内存空间
- 3、插入快,查询慢
02、链表的python实现
单链表节点类
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
节点创建
node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node1.next = node2
node2.next = node3
print(node2.data) # 2
print(node1.next.data) # 2
print(node1.next.next.data) # 3
print(node2.data) # 3
单链链表数据结构
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self, new_data):
self.data = new_data
class LinkedList:
def __init__(self):
self.head = None
self.length = 0
def __len__(self):
return self.length
def insert_head(self, node):
'''
插入节点
'''
self.head, node.next = node, self.head
self.length += 1
def __iter__(self):
'''
遍历链表
'''
head = self.head
while head is not None:
current, head = head, head.next
yield current
# 创建一个列表
linkedlist= LinkedList()
for i in range(10):
node = Node(i)
linkedlist.insert_head(node)
print(len(linkedlist)) # 10
print([node.data for node in linkedlist]) # [9,8,7,6,5,4,3,2,1,0]
单链表遍历
current = linkedlist.head
while current is not None:
current = current.next
从末尾插入数据
new_node = Node('new node')
current = linkedlist.head
while current is not None:
current = current.next
current.next = new_node
def append_node(self, node):
'''
末尾插入节点
'''
current = self.head
while current.next is not None:
current = current.next
current.next = node
self.length += 1
new_node = Node('new Node')
linkedList.append_node(new_node)
print([node.data for node in linkedList]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 'new Node']
从开始处删除节点:
linkedlist.head = linkedlist.head.next
# 弹出并返回第一个节点
def pop_first(self):
head = self.head
if self.head is not None:
self.head = self.head.next
self.length -= 1
return head
d = linkedlist.pop_first()
print(d.data) # 9
print([node.data for node in linkedList]) # [8, 7, 6, 5, 4, 3, 2, 1, 0, 'new Node']
从末尾处删除:
current = linkedlist.head
while current.next.next is not None:
current = current.next
current.next = None
# 弹出最后一个节点
def pop_last(self):
current = self.head
while current.next.next is not None:
current = current.next
node, current.next = current.next, None
self.length -= 1
return node
d = linkedlist.pop_last()
print(d.data) # new node
print([node.data for node in linkedlist]) # [8,7,6,5,4,3,2,1,0]
从任意处插入数据:
new_node = Node("new_index")
if linkedlist.head is None or index < 1:
linkedlist.head, new_node.next = new_node, linkedlist.head
else:
current = linkedlist.head
while index > 1 and current.next is not None:
current = current.next
index -= 1
current.next, new_node.next = new_node, current.next
# 从index处插入节点
def insert(self, index, new_node):
if self.head is None or index < 1:
self.head, new_node.next = new_node, self.head
else:
current = self.head
while index > 1 and current.next i not None:
current = current.next
index -= 1
current.next, new_node.next = new_node, current.next
self.length += 1
# 从第index处插入节点
index = 3
new_node = Node("new_index")
linkedlist.insert(index, new_node)
print(len(linkedlist)) # 10
print([node.data for node in linkedlist]) # [8, 7, 6, 'new_index', 5, 4, 3, 2, 1, 0]
从任意处删除数据:
if linkedlist.head.next is None or index < 0:
linkedlist.head = None
else:
current = linkedlist.head
while index > 1 and current.next is not None:
current = current.next
index -= 1
current.next = current.next.next
# 删除index处节点
def remove(self, index):
if self.head is None or index < 0:
return None
else:
current = self.head
while index > 1 and current.next is not None:
current = current.next
index -= 1
current.next = current.next.next
self.legnth -= 1
# 删除index处节点
index = 4
linkedlist.remove(index)
print(len(linkedlist)) # 9
print([node.data for node in linkedlist]) # [8, 7, 6, 'new_index', 4, 3, 2, 1, 0]
03.时间复杂度:
各项操作时间复杂度
操作 | 复杂度 |
---|---|
从第i个位置访问 | O(n) |
在第i个位置替换 | O(n) |
从末尾插入数据 | O(n) |
从末尾删除 | O(n) |
从第i个位置插入 | O(n) |
从第i个位置删除 | O(n) |
从开始处插入 | O(1) |
从开始处删除 | O(1) |
课外练习:用Python实现双链表的上述操作(面试常考)
单链表优势:
1、内存空间利用率高(不需要连续内存空间),空间复杂度低
2、适合开始处插入,开始处读取的场景
三、课程小结
- 学习了链表结构
- 学习了单链表的实现
- 学习了单链表操作的时间复杂度
本节课单链表操作全部代码:
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self, new_data):
self.data = new_data
class LinkedList:
def __init__(self):
self.head = None
self.length = 0
def __len__(self):
return self.length
def insert_head(self, node):
'''
插入节点
'''
self.head, node.next = node, self.head
self.length += 1
def __iter__(self):
'''
遍历链表
'''
head = self.head
while head is not None:
current, head = head, head.next
yield current
def append_node(self, node):
'''
末尾插入节点
'''
current = self.head
while current.next is not None:
current = current.next
current.next = node
self.length += 1
def pop_first(self):
'''
弹出并返回第一个节点
'''
head = self.head
if self.head is not None:
self.head = self.head.next
self.length -= 1
return head
def pop_last(self):
'''
弹出最后一个节点
'''
current = self.head
while current.next.next is not None:
current = current.next
node, current.next = current.next, None
self.length -= 1
return node
def insert(self, index, new_node):
'''
在第index处插入数据
'''
if self.head is None or index < 1:
self.head, new_node.next = new_node, self.head
else:
current = self.head
while index > 1 and current.next is not None:
current = current.next
index -= 1
current.next, new_node.next = new_node, current.next
self.length += 1
def remove(self, index):
'''
删除index处节点
'''
if self.head is None or index < 0:
return None
else:
current = self.head
while index > 1 and current.next is not None:
current = current.next
index -= 1
current.next = current.next.next
self.length -= 1
# 创建一个列表
linkedlist = LinkedList()
for i in range(10):
node = Node(i)
linkedlist.insert_head(node)
print(len(linkedlist)) # 10
print([node.data for node in linkedlist]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# 在末尾处插入节点
new_node = Node('new Node')
linkedlist.append_node(new_node)
print(len(linkedlist)) # 11
print([node.data for node in linkedlist]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 'new Node']
# 弹出并返回第一个节点
d = linkedlist.pop_first()
print(d.data) # 9
print(len(linkedlist)) # 10
print([node.data for node in linkedlist]) # [8, 7, 6, 5, 4, 3, 2, 1, 0, 'new Node']
# 弹出最后一个节点
d = linkedlist.pop_last()
print(d.data) # new Node
print(len(linkedlist)) # 9
print([node.data for node in linkedlist]) # [8, 7, 6, 5, 4, 3, 2, 1, 0]
# 从第index处插入节点
index = 3
new_node = Node("new_index")
linkedlist.insert(index, new_node)
print(len(linkedlist)) # 10
print([node.data for node in linkedlist]) # [8, 7, 6, 'new_index', 5, 4, 3, 2, 1, 0]
# 删除index处节点
index = 4
linkedlist.remove(index)
print(len(linkedlist)) # 9
print([node.data for node in linkedlist]) # [8, 7, 6, 'new_index', 4, 3, 2, 1, 0]