2. python实现单链表
2. python实现单链表
1. 创建Node节点
- 初始化节点属性 数据域和下一个节点的指针域
- 设置data属性,更加pythonic写法,类方法加
@property
转化为属性使用 - 修改属性
- 同样实现下一个节点指针的属性和修改
1 | class Node(object): |
2. 创建单链表及方法
这里实现的单链表操作方法有:
查找
- 按值查找
- 按索引查找节点
插入
- 头结点插入指定值
- 在链表指定节点后插入值为value的节点
- 在链表指定节点之前插入值为value的节点
删除
- 删除指定节点
- 删除指定值的节点
- 删除链表中倒数第n个节点
一般方法
创建一个节点
打印当前链表所有节点数据
常见单链表考点
查找链表中间节点
翻转相邻两个节点
- 翻转链表
- 检查链表是否有环
初始化单链表私有头结点属性
1
2
3
4class SingleLinkList(object):
"""单向链表类"""
def __init__(self):
self.__head = None
按值查找
1
2
3
4
5
6
7
8
9
10
11def find_by_value(self, value):
"""
按照指定值在单向链表中查找
:param value: 查找的指定值
:return: node
"""
node = self.__head
while (node is not None) and (node.data != value):
# 如果节点不为空且节点值不等于查找值就一直往后查找
node = node.next_node
return node
按索引查找节点
1
2
3
4
5
6
7
8
9
10
11
12
13def find_by_index(self, index):
"""
按照指定索引在单向链表中查找
:param index: 查找的指定索引
:return: node
"""
node = self.__head
pos = 0
while (node is not None) and (pos != index):
# 如果节点不空且索引不是查找的,节点网后移一个,索引也往后移一个
node = node.next_node
pos += 1
return node头结点插入指定值
1
2
3
4
5
6
7
8
9def insert_node_to_head(self, value):
"""
链表头部插入值为value的节点
:param value: 要插入的值
"""
node = Node(value)
#插入节点的下一个节点指向头, 头结点指向插入节点
node.next_node = self.__head
self.__head = node在链表指定节点后插入值为value的节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14def insert_after(self, node, value):
"""
在链表指定节点后插入一个值为value的node
:param node: 指定的节点
:param value: 要插入的值
"""
if node is None: # 指定节点为空就什么都不做
return
new_node = Node(value)
# 将指定节点的下一个节点指针赋值给新节点的下一个指针
new_node.next_node = node.next_node
# 新节点接到指定节点后
node.next_node = new_node在链表指定节点之前插入值为value的节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27def insert_before(self, node, value):
"""
在指定节点前插入值为value的节点
:param node: 指定节点
:param value: 插入的值
"""
if (node is None) and (self.__head is None):
# 如果指定节点是空或者空链表之前插入数据,则什么都不做
return
if node == self.__head:
# 如果指定节点是头结点就直接用头结点插入
self.insert_to_head(value)
return
new_node = Node(value)
pos = self.__head # 设置位置节点为头结点
not_found = False # 没找到标志位
while pos.next_node != node: # 寻找节点直到等于指定节点
if pos.next_node is not None: # 如果当前位置的下一个节点不为空,继续后移位置
pos = pos.next_node
else: # 直到链表最后节点,没找到指定节点,将没找到标志位置为True,并跳出循环
not_found = True
break
if not not_found: # 找到指定节点的前节点就插入node
pos.next_node = new_node
new_node.next_node = node删除指定节点,类似于7插入指定节点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22def delete_by_node(self, node):
"""
删除链表指定节点
:param node: 指定节点
"""
if self.__head is None: # 如果头结点为空,就不用删除直接返回
return
if node == self.__head:
# 如果指定节点是头结点,直接将头结点接到节点下一个节点
self.__head = node.next_node
return
pos = self.__head
not_found = False
while pos.next_node != node:
if pos.next_node is not None: # 如果当前位置的下一个节点不为空,继续后移到下一个位置
pos = pos.next_node
else: # 直到链表最后节点,没找到指定节点,将没找到标志位置为True,并跳出循环
not_found = True
break
if not not_found:
pos.next_node = node.next_node删除指定值的节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24def delete_by_value(self, value):
"""
删除链表中指定值节点
:param value: 删除的指定值
"""
if self.__head is None:
return
if self.__head.data == value:
# 如果头节点值就等于删除值,直接将头结点指向下一个节点
self.__head = self.__head.next_node
pos = self.__head # 位置位
node = self.__head.next_node # 第一个节点
not_found = False
while node.data != value: # 节点值不为删除值
if node.next_node is not None: # 如果当前节点的下一个节点不为空,继续后移位置节点
pos = node
node = node.next_node
else: # 直到链表最后节点,没找到指定节点,将没找到标志位置为True,并跳出循环
not_found = True
break
if not not_found:
pos.next_node = node.next_node
删除链表中倒数第n个节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20def delete_last_n_node(self, n):
"""
删除链表中倒数第n个节点
主体思路:
设置快慢指针,快指针先行n步,然后快慢指针同时往后移,
当快指针到链表尾部时,直接将这时慢指针的下一个节点接到第n个节点上
:param n: 删除倒数第n个节点
"""
fast = self.__head
slow = self.__head
step = 0
while step <= n:
fast = fast.next_node
step += 1
while fast.next_node is not None:
tmp = slow
fast = fast.next_node
slow = slow.next_node
tmp.next_node = slow.next_node
查找链表中间节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14def find_mid_node(self):
"""
查找链表中的中间节点
主体思路,依旧是快慢指针,快指针走2步,慢指针走1步,
当快指针到链表尾部时,慢指针刚好到中间
:return: 中间节点
"""
fast = self.__head
slow = self.__head
while fast.next_node is not None:
fast = fast.next_node.next_node
slow = slow.next_node
return slow创建一个节点
1
2
3
4
5
6
7def create_node(self, value):
"""
创建值为value的node
:param value: 创建节点的值
:return: 创建的节点
"""
return Node(value)打印当前链表所有节点数据
1
2
3
4
5
6
7
8
9
10
11
12
13def print_all(self):
"""
打印当前链表所有节点数据
"""
pos = self.__head
if pos is None:
print("当前链表为空")
return
while pos.next_node is not None:
print(str(pos.data) + "-->", end="")
pos = pos.next_node
print(str(pos.data))翻转相邻两个节点
1
2
3
4
5
6
7
8
9
10
11
12def __reversed_with_two_node(self, pre, node):
"""
翻转相邻两个节点
:param pre: 前一个节点
:param node: 当前节点
:return: (pre, node)
"""
tmp = node.next_node
node.next_node = pre
pre = node # 啰嗦点但更容易理解
node = tmp
return pre, node
翻转链表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def reversed_list(self):
"""
翻转链表
"""
if self.__head is None or self.__head.next_node is None:
# 链表为空或只有一个节点直接返回
return
pre = self.__head
node = self.__head.next_node
# 当下一个节点不为空,翻转两个节点
while node is not None:
pre, node = self.__reversed_with_two_node(pre, node)
self.__head.next_node = None
self.__head = pre
检查链表是否有环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def has_ring(self):
"""
检查链表是否有环, 快慢指针相遇为环
:return: True or False
"""
fast = self.__head
slow = self.__head
while (fast is not None) and (fast.next_node is not None):
# 注意一定要有fast的下一个节点也不空
slow = slow.next_node
fast = fast.next_node.next_node
if fast == slow:
return True
return False
对上述代码进行测试如下:
1 | if __name__ == "__main__": |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 aigonna!
评论