链表是一种线性表数据结构
对于c++来说,构建链表是通过结构体和指针来实现的
而对于Python来说,链表是通过类来创建的
链表是由链节点通过next连接而成的,每个链节点存放一个数据元素,还存放一个后继指针,用于指出其后继元素所在链节点的地址
在Python中实现单链表,先定义一个链节点类:
class ListNode:
def __init__(self,val = 0,next = None): # val表示数据元素的值,next表示后继指针
self.val = val
self.next = next
然后定义完整的链表类:
class LinkedList:
def __init__(self):
self.head = None # 链节点变量head表示链表的头节点
然后在链表类里,定义链表基本操作的实例方法:
# 1 根据data建立一个新链表
def create(self,data):
self.head = ListNode(0) # 实例化对象,头节点对应的元素一般设置为0
cur = self.head
for i in range(len(data)):
node = ListNode(data[i]) # 实例化对象
cur.next = node
cur = node
# 2 求线性链表长度
def length(self):
count = 0
cur = self.head # 遍历链表指针,count指针指向链节点
while cur:
count += 1
cur = cur.next
return count
# 3 在链表中查找值为val的元素
def find(self,val):
cur = self.head
while cur:
if cur.val == val:
return cur # 查找成功,返回被查找节点的地址
cur = cur.next
return None
# 4 在链表头部插入元素(插在了头节点之前),此时头结点就变成了它
def insertFront(self,val):
node = ListNode(val)
node.next = self.head
self.head = node
# 5 在链表尾部插入元素
def insertRear(self,val):
cur = self.head
while cur.next:
cur = cur.next
node = ListNode(val)
cur.next = node
# 6 在链表中间插入元素
def insertInside(self,index,val): #在链表下标为index(即第index个链节点)的节点之前插入值为val的链节点
count = 0
cur = self.head
while cur and count < index - 1:
cur = cur.next
count += 1
if not cur:
return 'Error'
node = ListNode(val)
node.next = cur.next
cur.next = node
# 7 将链表中下标为index(即第index个链节点,注意不包括头节点)的元素的值改为val
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
# 8 删除链表的第一个链节点
def removeFront(self):
if self.head:
self.head = self.head.next
# 9 删除链表的最后一个链节点
def removeRear(self):
if not self.head.next or not self.head:
return 'Error'
cur = self.head
while cur.next.next:
cur = cur.next
cur.next = None
# 10 删除链表下标为index的链节点
def removeInside(self,index):
cur = self.head
count = 0
while cur.next and count < index - 1:
count += 1
cur = cur.next
if not cur:
return 'Error'
cur.next = cur.next.next
为了方便查看链表中每个链节点所存放的数据元素,我还自定义了一个输出链表元素的实例方法:
def disp(self):
blist = []
cur = self.head
while cur:
blist.append(cur.val)
cur = cur.next
print(blist)
验证代码如下:
alist = LinkedList()
alist.create([1,2,3,4,5,6])
print(f"链表的长度为{alist.length()}")
print(f'值为4的元素的地址为{alist.find(4)}')
print('经过插入操作的链表变为:')
alist.insertFront(7)
alist.insertRear(10)
alist.insertInside(3,12)
alist.disp()
print('经过删除操作的链表变为:')
alist.removeFront()
alist.removeRear()
alist.removeInside(6)
alist.disp()
代码测试结果如下:
需要注意的是,我这里创建的链表是有头结点的
而下面我将以leetcode0707题为例,建立一个不带头结点的单链表,大家要注意两种链表的区别和联系
创建链节点类:
class ListNode:
def __init__(self, val):
self.val = val
self.next = None
创建链表类:
class MyLinkedList:
def __init__(self):
self.size = 0 #size保存有效节点数
self.head = ListNode(0) #head是头结点 注意下标为0的节点是head.next 可理解为不带头结点的链表
然后在链表类里,定义链表基本操作的实例方法:
def get(self, index): #获取链表中下标为 index 的节点的值
if index < 0 or index >= self.size:
return -1
cur = self.head
for i in range(index + 1):
cur = cur.next
return cur.val
def addAtHead(self, val): #将一个值为 val 的节点插入到链表中第一个元素之前
self.addAtIndex(0, val)
def addAtTail(self, val): #将一个值为 val 的节点追加到链表中作为链表的最后一个元素
self.addAtIndex(self.size, val)
def addAtIndex(self, index, val): #将一个值为 val的节点插入到链表中下标为 index 的节点之前
if index > self.size:
return
index = max(0, index)
self.size += 1
pred = self.head
for i in range(index):
pred = pred.next
node = ListNode(val)
node.next = pred.next
pred.next = node
def deleteAtIndex(self, index): #删除链表中下标为 index 的节点
if index < 0 or index >= self.size:
return
self.size -= 1
pred = self.head
for i in range(index):
pred = pred.next
pred.next = pred.next.next
为了便于查看链表中每个链节点所存储的元素,我同样定义了链表输出方法:
def disp(self):
blist = []
cur = self.head.next
while cur:
blist.append(cur.val)
cur = cur.next
print(blist)
验证代码如下:
alist = MyLinkedList()
alist.size = 6
cur = alist.head #构造原始链表
for i in range(alist.size):
n = int(input('请输入数据:'))
cur.next = ListNode(n)
cur = cur.next
print('原始链表的元素为:')
alist.disp()
alist.addAtHead(12)
alist.addAtTail(13)
alist.addAtIndex(3,7)
print('增加元素后的链表的元素为:')
alist.disp()
alist.deleteAtIndex(4)
print('删除元素后的链表的元素为:')
alist.disp()
代码测试结果如下:
此上就是我的心得体会,如有不足,望各位予以纠正