笔者在前面已经介绍过了栈的实现和队列的实现,本文则是介绍链表的实现,包括单向链表和双向链表的实现。希望能够给初学python算法和数据结构的小伙伴提供帮助~
首先看下单链表的实现,通常单链表中的节点一般包含两个属性,一是存储该节点的数据,二是指向下一节点的指针。因此,在实现单链表之前,我们需要定义如下的 单链表节点
。
class SingleLinkNode:
"""
Single Link Node definition
"""
def __init__(self, data=None):
self.data = data
self.next = None
定义好单链表节点之后,接下来就是对单链表进行实现了。这里实现的单链表主要包含以下几个操作:在单链表末尾添加元素
(append方法)、在单链表指定位置插入元素
(insert方法)、删除单链表中第一个出现的指定元素
(remove方法)、获取单链表中某个位置的元素值
(getValue方法)、清空单链表
(clear方法)、反转单链表
(reverse方法)、获取单链表中元素个数
(length方法)、判断单链表是否为空
(isEmpty方法)、打印整个单链表
(print_all方法)。以下是上面所有方法的实现代码,值得注意的是在 insert 和 getValue 方法中,需要对 index 为负数的情况进行处理下(即加上单链表的长度),因为理论上索引是支持负数的。
class SingleLinkList:
"""
Single Link List implement
"""
def __init__(self):
"""
Initialize an empty pointer
"""
self.__head = None
def append(self, obj):
"""
append an element at tail
:param obj: object for appending
"""
node = SingleLinkNode(obj)
if self.isEmpty():
self.__head = node
else:
curr = self.__head
while curr.next:
curr = curr.next
curr.next = node
def insert(self, obj, index):
"""
insert an element at specific position
:param obj: object for inserting
:param index: target position
"""
node = SingleLinkNode(obj)
if self.isEmpty():
self.__head = node
else:
length = self.length()
index = index if index >= 0 else length + index
# insert at the first position
if index == 0:
curr = self.__head
node.next = curr
self.__head = node
elif 0 < index < length:
count = 1
curr = self.__head
while curr.next:
if count == index:
node.next = curr.next
curr.next = node
break
else:
count += 1
curr = curr.next
# if index is out of range, insert at last position
else:
self.append(obj)
def remove(self, obj):
"""
remove the first element of target object
:param obj: target object
"""
if self.isEmpty():
pass
# remove the first element
elif self.__head.data == obj:
self.__head = self.__head.next
else:
curr = self.__head
while curr.next:
if curr.next.data == obj:
curr.next = curr.next.next
break
else:
curr = curr.next
def getValue(self, index):
"""
get value of specific position
:param index: specific position
:return: value
"""
if self.isEmpty():
return None
length = self.length()
index = index if index >= 0 else length + index
if 0 <= index < length:
count = 0
curr = self.__head
while curr:
if count == index:
return curr.data
else:
count += 1
curr = curr.next
else:
return None
def clear(self):
"""
clear the whole Single Link List
"""
self.__head = None
def reverse(self):
"""
reverse the Single Link List
"""
if self.isEmpty() or self.length() == 1:
return
curr = self.__head
prev = None
while curr:
back = curr.next
curr.next = prev
prev = curr
curr = back
self.__head = prev
def length(self):
"""
get the length of Single Link List
:return:
"""
count = 0
curr = self.__head
while curr:
count += 1
curr = curr.next
return count
def isEmpty(self):
"""
judge the Single Link List is empty or not
:return: bool value
"""
return self.__head is None
def print_all(self):
"""
print all elements of Single Link List
"""
element = []
curr = self.__head
while curr:
element.append(curr.data)
curr = curr.next
print(element)
然后是双链表的实现,对比于单链表而言,双链表中的节点除了有存储该节点的值和指向下一节点的指针外,还需有指向前一节点的指针,所以首先需要定义好 双链表节点
,具体的定义如下:
class DoubleLinkNode:
"""
Double Link Node definition
"""
def __init__(self, data=None):
self.data = data
self.prev = None
self.next = None
双链表节点定义好之后,接着便是对双链表进行实现了,双链表同单链表一样具有相同的操作方法。具体的实现代码如下所示,说下需要注意的两个地方:
class DoubleLinkList:
"""
Double Link List implement
"""
def __init__(self):
"""
Initialize Double Link List
"""
self.__head = DoubleLinkNode()
self.__tail = DoubleLinkNode()
self.__head.next = self.__tail
self.__tail.prev = self.__head
def append(self, obj):
"""
append an element at tail
:param obj: object for appending
"""
node = DoubleLinkNode(obj)
prev_node = self.__tail.prev
self.__tail.prev = node
node.next = self.__tail
node.prev = prev_node
prev_node.next = node
def insert(self, obj, index):
"""
insert an element at specific position
:param obj: object for inserting
:param index: target position
"""
node = DoubleLinkNode(obj)
length = self.length()
index = index if index >= 0 else length + index
# insert at the first position
if index == 0:
back = self.__head.next
self.__head.next = node
node.prev = self.__head
node.next = back
back.prev = node
elif 0 < index < length:
count = 1
curr = self.__head
while curr.next != self.__tail:
if count == index:
node.prev = curr
node.next = curr.next
curr.next.prev = node
curr.next = node
break
else:
count += 1
curr = curr.next
# if index is out of range, insert at last position
else:
self.append(obj)
def remove(self, obj):
"""
remove the first element of target object
:param obj: target object
"""
if self.isEmpty():
pass
else:
curr = self.__head.next
while curr != self.__tail:
if curr.data == obj:
prev_node = curr.prev
prev_node.next = curr.next
curr.next.prev = prev_node
break
else:
curr = curr.next
def getValue(self, index):
"""
get value of specific position
:param index: specific position
:return: value
"""
if self.isEmpty():
return None
length = self.length()
index = index if index >= 0 else length + index
if 0 <= index < length:
count = 0
curr = self.__head.next
while curr != self.__tail:
if count == index:
return curr.data
else:
count += 1
curr = curr.next
else:
return None
def clear(self):
"""
clear the whole Double Link List
"""
self.__head.next = self.__tail
self.__tail.prev = self.__head
def reverse(self):
"""
reverse the Double Link List
"""
if self.isEmpty() or self.length() == 1:
return
prev = self.__tail
curr = self.__head.next
while curr != self.__tail:
back = curr.next
if back != self.__tail:
curr.prev = back
else:
# deal with head
curr.prev = self.__head
self.__head.next = curr
curr.next = prev
# deal with tail
if prev == self.__tail:
self.__tail.prev = curr
prev = curr
curr = back
self.__head.prev = self.__tail.next = None
def length(self):
"""
get the length of Double Link List
:return:
"""
count = 0
curr = self.__head
while curr.next != self.__tail:
count += 1
curr = curr.next
return count
def isEmpty(self):
"""
judge the Double Link List is empty or not
:return: bool value
"""
return self.__head.next == self.__tail
def print_all(self):
"""
print all elements of Double Link List
"""
element = []
curr = self.__head.next
while curr != self.__tail:
element.append(curr.data)
curr = curr.next
print(element)
关于其他常用数据结构的实现,可参考下面的链接: