之前写了一组代码,实现了一些单向链表的操作。作为小白,写的比较臃肿。又把增删改查等类似操作整合了一下,这里的代码对比上一篇中的稍微简洁了些
大体思路
和上一篇的思路一样,写两个类:
- Node类:用于创建结点,并将结点以(人类)能看懂的字符串形式输出,而不是显示内存地址
- LinkedList类:在这一类下的方法里做了改动。这个类用于将各结点连成链表,并实现对链表进行操作的一些方法
创建Node类:
class Node:
def __init__(self, data, next=None):
self.data = data # 数据,当前结点的元素
self.next = None # 指针,指向下一个结点
def __repr__(self): # 把结点表示为一个字符串
return "NodeValue({})".format(self.data)
调用测试:
n = Node(1)
print(n) # 因为写了__repr__方法,所以输出的是Node(1),而不是内存地址
创建LinkedList类:
准备工作:初始化方法 & 打印字符串方法
想要达到的输出效果类似于:
NodeValue(1) --> NodeValue(3) --> NodeValue(4) --> END
class LinkedList:
def __init__(self):
self.head = None # 初始化头结点
self.tail = None # 初始化尾结点
self.size = 0 # 初始化链表长度
## 打印链表
def __repr__(self):
cursor = self.head
string_repr = ""
while cursor:
# 以f开头,表示在字符串内支持大括号内的python表达式
string_repr += f"{cursor} --> "
cursor = cursor.next
return string_repr + "END"
下面开始是实现方法的代码:
1. get(index) 传入索引,返回在该索引位置的结点
# 传入索引,返回在该索引位置的结点
def get(self, index):
"""
:param index: 索引,从左数从0开始,从右数从-1开始
"""
# 将索引变为从左数开始数的正数索引
if index >= 0:
leftindex = index
else:
leftindex = index + self.size
# 返回节点
current = self.head
for i in range(leftindex):
current = current.next
return current
2. insert(index, data) 向链表中指定位置插入结点
def insert(self, index, data):
# 将索引变为从左数开始数的正数索引
if index < 0:
# leftindex最小值为1,最大值为self.size
leftindex = self.size + index + 1
else:
leftindex = index
new_node = Node(data)
if (index >= 0 and index > (self.size)) or (index < 0 and leftindex > self.size): # 如果传入的索引越界,报错
self.size -= 1
raise Exception("Index out of range")
elif self.size == 0: # 如果当前是一个空链表
self.head = new_node
self.tail = new_node
self.size += 1
elif index == 0 or (index < 0 and leftindex == 1): # 用户想要在头部插入结点
new_node.next = self.head
self.head = new_node
self.size += 1
elif index == (self.size-1) or index == -1: # 用户想要在尾部插入结点
print("尾部插入")
self.tail.next = new_node
self.tail = new_node
self.size += 1
else: # 用户想要在中间插入结点
if index >= 0:
pre = self.get(index - 1)
new_node.next = pre.next
pre.next = new_node
self.size += 1
else:
pre = self.get(leftindex - 1)
new_node.next = pre.next
pre.next = new_node
self.size += 1
3. remove(index, data) 删除链表中指定位置的结点
def remove(self, index):
# 将索引变为从左数开始数的正数索引
if index < 0:
# 这里的leftindex最小值为0,最大值为self.size
# 和左数正数索引一致
leftindex = index + self.size
else:
leftindex = index
if leftindex < 0 or leftindex >= self.size: # 如果传入的索引越界,报错
raise Exception("Index out of range")
if leftindex == 0: # 用户想要删除头部结点
remove_node = self.head
self.head = self.head.next
elif leftindex == (self.size-1): # 用户想要删除尾部结点
pre = self.get(leftindex-1)
remove_node = pre.next
pre.next = None
self.tail = pre
else: # 用户想要中间的结点
pre = self.get(leftindex-1)
remove_node = pre.next
pre.next = pre.next.next
self.size -= 1
return remove_node.data
4. reverse() 反转链表
def reverse(self):
if self.size == 0 or self.size == 1:
return self
else:
current = self.head
pre = None
while current:
# 储存当前结点的正序下一个结点
next_node = current.next
# 让当前结点的下一个结点指向前一个结点
current.next = pre
# 前结点后移
pre = current
# 当前结点后移
current = next_node
# 更改头结点
self.head = pre
self.tail = next_node
return self
-
Info
- Author: Shanshan Yan
- Wechat: shanshan700224
- Copyright: All rights reserved