所有动画演示可以在VisuAlgo这个网站上找到。
类中所有函数均通过测试,无误。
链表
链表(linked_list)是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间),另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。
复杂度分析
链表属于常见的一种线性结构,对于插入和移除而言,时间复杂度都为 O(1)。但是对于搜索操作而言,不管从链表的头部还是尾部,都需要遍历 O(n),所以最好复杂度为 O(1),最坏的情况就是从头部遍历到尾部才搜索出对应的元素,所以最坏复杂度为 O(n),平均复杂度为 O(n)。
单链表
class Node:
def __init__(self, data):
self.data = data
self.next = None
class Linkedlist:
def __init__(self):
self.head = None
def insertFront(self, new_data): # 在链表前面增加一个元素
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
def append(self, new_data): # 在链表后面增加一个元素
new_node = Node(new_data)
current = self.head
if self.head:
while current.next:
current = current.next
current.next = new_node
else:
self.head = new_node
def insert(self, position, new_data): #在链表中指定索引处插入元素
if position < 0 or position > self.get_length():
raise IndexError('insert 插入时,key 的值超出了范围')
new_node = Node(new_data)
current = self.head
if position == 0:
new_node.next = self.head
self.head = new_node
return
# 遍历找到索引值为 position 的结点后, 在其后面插入结点
i = 0
while i < position:
temp = current
current = current.next
i += 1
temp.next = new_node
new_node.next = current
def remove(self, position): # 删除指定索引的链表元素
if position < 0 or position > self.get_length()-1:
raise IndexError('删除元素的位置超出范围')
current = self.head
# 遍历找到索引值为 position 的结点
i = 0
while current != None:
if position == 0:
self.head = current.next
current.next = None
return True
temp = current
current = current.next
i += 1
if i == position:
temp.next = current.next
current.next = None
return
def get_length(self): #获取链表的长度
# 临时变量指向队列头部
temp = self.head
# 计算链表的长度变量
length = 0
while temp != None:
length = length+1
temp = temp.next
# 返回链表的长度
return length
def printList(self): # 遍历链表,并将元素依次打印出来
print("linked_list:")
current = self.head
new_list = []
while current is not None:
new_list.append(current.data)
current = current.next
print(new_list)
def is_empty(self): #判断链表是否为空
return not self.head
def reverse(self): #将链表反转
prev = None
current = self.head
while current:
next_node = current.next
current.next = prev
prev = current
current = next_node
self.head = prev
def initlist(self,data_list): #将列表转换为链表
# 创建头结点
self.head = Node(data_list[0])
temp = self.head
# 逐个为 data 内的数据创建结点, 建立链表
for i in data_list[1:]:
node = Node(i)
temp.next = node
temp = temp.next
if __name__ == '__main__':
list = Linkedlist()
list.insertFront(1)
list.insertFront(2)
list.append(3)
list.append(4)
list.insert(0,0)
list.insert(1,5)
list.insert(4,6)
list.remove(0)
list.remove(2)
list.reverse()
list.printList()
单链表的应用
交换单链表里两个链点。给定两个值,如果这两个值都在单链表的链点中,即交换这两个链点在单链表的位置。
举例:
1->2->3->4->5
input:1 4 output:4->2->3->1->5
#在类中定义这个函数
def swapNodes(self, d1, d2):
prevD1 = None
prevD2 = None
if d1 == d2:
return
else:
D1 = self.head
while D1 is not None and D1.data != d1:
prevD1 = D1
D1 = D1.next
D2 = self.head
while D2 is not None and D2.data != d2:
prevD2 = D2
D2 = D2.next
if D1 is None and D2 is None:
return
if prevD1 is not None:
prevD1.next = D2
else:
self.head = D2
if prevD2 is not None:
prevD2.next = D1
else:
self.head = D1
temp = D1.next
D1.next = D2.next
D2.next = temp
if __name__ == '__main__':
list = Linkedlist()
list.append(1)
list.append(2)
list.append(3)
list.append(4)
list.append(5)
list.printList()
list.swapNodes(1, 4)
print("After swapping")
list.printList()
双链表
class Node(object):
# 双向链表节点
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
class DLinkList(object):
# 双向链表
def __init__(self):
self._head = None
def is_empty(self):
# 判断链表是否为空
return self._head == None
def get_length(self):
# 返回链表的长度
cur = self._head
length = 0
while cur != None:
length = length+1
cur = cur.next
return length
def travel(self):
# 遍历链表
cur = self._head
while cur != None:
print(cur.data)
cur = cur.next
print("")
def add(self, data):
# 头部插入元素
node = Node(data)
if self.is_empty():
# 如果是空链表,将 node 赋值给 _head
self._head = node
else:
# 将 node 的 next 属性指向头节点 _head
node.next = self._head
# 将头节点 _head 的 prev 属性指向 node
self._head.prev = node
# 将 node 赋值给 _head
self._head = node
def append(self, data):
# 尾部插入元素
node = Node(data)
if self.is_empty():
# 如果是空链表,将 node 赋值给 _head
self._head = node
else:
# 循环移动到链表尾部结点的位置
cur = self._head
while cur.next != None:
cur = cur.next
# 将尾结点 cur 的 next 属性指向 node
cur.next = node
# 将 node 的 prev 属性指向 cur
node.prev = cur
def search(self, data):
# 查找元素是否存在
cur = self._head
while cur != None:
if cur.data == data:
return True
cur = cur.next
return False
def insert(self, pos, data):
# 在指定位置添加节点
if pos <= 0:
self.add(data)
elif pos > (self.length()-1):
self.append(data)
else:
node = Node(data)
cur = self._head
count = 0
# 移动到指定位置的前一个位置
while count < (pos-1):
count += 1
cur = cur.next
# 将 node 的 prev 属性指向 cur
node.prev = cur
# 将 node 的 next 属性指向 cur 的下一个节点
node.next = cur.next
# 将 cur 的下一个节点的 prev 属性指向 node
cur.next.prev = node
# 将 cur 的 next 指向 node
cur.next = node
def remove(self, data):
# 删除元素
if self.is_empty():
return
else:
cur = self._head
if cur.data == data:
# 如果首节点的元素即是要删除的元素
if cur.next == None:
# 如果链表只有这一个节点
self._head = None
else:
# 将第二个节点的 prev 属性设置为 None
cur.next.prev = None
# 将 _head 指向第二个节点
self._head = cur.next
return
while cur != None:
if cur.data == data:
# 将 cur 的前一个节点的 next 指向 cur 的后一个节点
cur.prev.next = cur.next
# 将 cur 的后一个节点的 prev 指向 cur 的前一个节点
cur.next.prev = cur.prev
break
cur = cur.next