python中没有链表这种数据类型,所以需要先定义ListNode
类
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
如果定义上图的链表,代码为:
l3 = ListNode(3,None)
l2 = ListNode(2,l3)
l1 = ListNode(1, l2)
debug中可查看,与我们预期的一样
从头到尾读取链表
def read_list(head):
res = []
while head:
res.append(head.val)
head = head.next
return res
# 从头到尾读取链表
head = l1
res = read_list(head)
print(res)
结果为:[1, 2, 3]
从尾到头读取链表
# 从尾到头读取链表
def read_list_rev(head):
res = []
while head:
res.insert(0, head.val)
head = head.next
return res
head = l1
res = read_list_rev(head)
print(res)
结果为:[3, 2, 1]
获取链表长度
# 获取链表长度
def list_len(head):
length = 0
while head:
length += 1
head = head.next
return length
head = l1
length = list_len(head)
print(length)
结果为:3
清空链表
# 清空链表
def clear(head):
head = None
return head
head = l1
head = clear(head)
res = read_list(head)
print(res)
结果为:[]
追加节点
若第一个节点就为None,则直接赋值;
若第一个节点不为None,则找到最后一个节点,然后加在最后面。
要注意的是:
- 不能直接用head,要用个pre去索引,因为虽然我们追加是加在最后面,但是我们索引链表的话,还是需要从表头找起的,所以不能损坏表头;
- while处不能是pre,因为如果是pre的话,跳出while循环时就已经是指向最后一个节点的下一个节点的了,所以是
while pre.next
。
# 追加节点
def node_append(head, new_node):
if head is None:
head = new_node
else:
pre = head
while pre.next:
pre = pre.next
pre.next = new_node
return head
head = l1
l4 = ListNode(4,None)
head = node_append(head, l4)
res = read_list(head)
print(res)
结果为:[1, 2, 3, 4]
获取节点
要注意的是index的正负,若为-1即为倒数第一个,所以需要list_len(head)+index
# 获取节点
def get_node(head, index):
if index>=0:
index=index
else:
index = list_len(head)+index
while index:
head = head.next
index -= 1
return head
head = l1
index = -1
head = get_node(head, index)
res = read_list(head)
print(res)
head = l1
index = 1
head = get_node(head, index)
res = read_list(head)
print(res)
结果为:
受上一题的影响所以会有4[4]
[2, 3, 4]
,为什么会输出三个数?因为在这里会获取index为1的节点,而不是index为1的节点值,所以当read_list
的时候会后面所有节点的值读出来。
设置节点
# 设置节点
def set_node(head, index, val):
if index>=0:
index=index
else:
index = list_len(head)+index
pre = head
while index:
pre = pre.next
index -= 1
pre.val = val
return head
head = l1
index = 1
val = 5
head = set_node(head, index, val)
res = read_list(head)
print(res)
结果为:[1, 5, 3, 4]
插入节点
要注意边界值的判断!
# 插入节点
def node_insert(head, index, new_node):
# 长度边界值判断
if abs(index+1) > list_len(head):
return False
# 特殊位置判断
if index == 0:
new_node.next = head
head = new_node
else:
if index > 0:
index = index
else:
index = list_len(head) + index
# 找到插入位置的上一个节点
pre = head
index -= 1
while index:
pre = pre.next
index -= 1
new_node.next = pre.next
pre.next = new_node
return head
head = l1
index = 2
l6 = ListNode(6,None)
head = node_insert(head, index, l6)
res = read_list(head)
print(res)
结果为:[1, 5, 6, 3, 4]
出现5是因为上一题的原因导致
上述代码中也可以调用get_node
来减少重复功能的代码
删除节点
越到后面,临界判断越多!
# 删除节点
def del_node(head, index):
if index>=0:
index=index
else:
index = list_len(head)+index
# 特殊情况判断
if abs(index+1) > list_len(head):
return False
elif index == 0:
head = None
else:
# 找到删除位置的上一个节点
pre = head
index -= 1
while index:
pre = pre.next
index -= 1
node_next = pre.next
pre.next = node_next.next
return head
head = l1
index = 1
head = del_node(head, index)
res = read_list(head)
print(res)
结果为:
删除前:[1, 5, 6, 3, 4]
删除后:[1, 6, 3, 4]
反转链表
特殊情况:表头为None或者只有一个节点
这里需要三个节点同时存储:pre指向一个节点的地址,head指向当前节点的地址,tmp指向下一节点的地址。
# 反转链表
def rev_node(head):
# 特殊情况判断
if head is None or head.next is None:
return head
pre = None
while head:
tmp = head.next
head.next = pre
pre = head
head = tmp
return pre
结果为:[4, 3, 6, 1]
部分代码参考:
完整代码
class ListNode:
def __init__(self, x, next):
self.val = x
self.next = next
l3 = ListNode(3, None)
l2 = ListNode(2, l3)
l1 = ListNode(1, l2)
# 从头到尾读取链表
def read_list(head):
res = []
while head:
res.append(head.val)
head = head.next
return res
head = l1
res = read_list(head)
print(res)
# 从尾到头读取链表
def read_list_rev(head):
res = []
while head:
res.insert(0, head.val)
head = head.next
return res
head = l1
res = read_list_rev(head)
print(res)
# 获取链表长度
def list_len(head):
length = 0
while head:
length += 1
head = head.next
return length
head = l1
length = list_len(head)
print(length)
# 清空链表
def clear(head):
head = None
return head
head = l1
head = clear(head)
res = read_list(head)
print(res)
# 追加节点
def node_append(head, new_node):
if head is None:
head = new_node
else:
pre = head
while pre.next:
pre = pre.next
pre.next = new_node
return head
head = l1
l4 = ListNode(4,None)
head = node_append(head, l4)
res = read_list(head)
print(res)
# 获取节点
def get_node(head, index):
if index>=0:
index=index
else:
index = list_len(head)+index
while index:
head = head.next
index -= 1
return head
head = l1
index = -1
head = get_node(head, index)
res = read_list(head)
print(res)
head = l1
index = 1
head = get_node(head, index)
res = read_list(head)
print(res)
# 设置节点
def set_node(head, index, val):
if index>=0:
index=index
else:
index = list_len(head)+index
pre = head
while index:
pre = pre.next
index -= 1
pre.val = val
return head
head = l1
index = 1
val = 5
head = set_node(head, index, val)
res = read_list(head)
print(res)
# 插入节点
def node_insert(head, index, new_node):
if index>=0:
index=index
else:
index = list_len(head)+index
# 长度边界值判断
if abs(index+1) > list_len(head):
return False
# 特殊位置判断
if index == 0:
new_node.next = head
head = new_node
else:
# 找到插入位置的上一个节点
pre = head
index -= 1
while index:
pre = pre.next
index -= 1
new_node.next = pre.next
pre.next = new_node
return head
head = l1
index = 2
l6 = ListNode(6,None)
head = node_insert(head, index, l6)
res = read_list(head)
print(res)
# 删除节点
def del_node(head, index):
if index>=0:
index=index
else:
index = list_len(head)+index
# 特殊情况判断
if abs(index+1) > list_len(head):
return False
elif index == 0:
head = None
else:
# 找到删除位置的上一个节点
pre = head
index -= 1
while index:
pre = pre.next
index -= 1
node_next = pre.next
pre.next = node_next.next
return head
head = l1
index = 1
res = read_list(head)
print(res)
head = del_node(head, index)
res = read_list(head)
print(res)
# 反转链表
def rev_node(head):
# 特殊情况判断
if head is None or head.next is None:
return head
pre = None
while head:
tmp = head.next
head.next = pre
pre = head
head = tmp
return pre
head = l1
res = read_list(head)
print(res)
head = rev_node(head)
res = read_list(head)
print(res)