python数据结构——链表
文章目录
- python数据结构——链表
- 单链表
- 概述
- 单向链表实现:
- 单链表优化
- 链表尾端插入优化
- 循环单链表
单链表
概述
数据结构是计算机科学必须掌握的一门学科,在C语言中,可以使用“指针+结构体”来实现链表;而在python中,则可以采用“引用+类”来实现链表。
链表的定义:是一组数据项的集合,其中每个数据项都是一个节点的一部分,每个节点还包含指向下一个节点的链接。
链表的结构:data 为自定义的数据,next为下一个节点的地址,head为保存首位节点的地址:
单向链表实现:
单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的指针。
示意图:
单链表删除节点:
单链表增加节点:
单链表的特点是:节点的链接方向是单向的;相对于数组来说,单链表的的随机访问速度较慢,但是单链表删除/添加数据的效率很高。
class Node:
def __init__(self,data):
self.data = data
self.next = None
class chain:
def __init__(self):
self.head = None
def is_empty(self):
return not self.head
def length(self):
count = 0
cur = self.head
while cur != None:
count += 1
cur = cur.next
return count
def add(self,data):
node = Node(data)
node.next = self.head
self.head = node
def append(self,data):
cur = self.head
while cur.next != None:
cur = cur.next
node = Node(data)
cur.next = node
def traverse(self):
cur = self.head
while cur != None:
print(cur.data, end='-***-')
cur = cur.next
print()
def insert(self,index,data):
if index < 0:
self.add(data)
elif index > self.length() -1:
self.append(data)
else:
cur = self.head
for i in range(index - 1):
cur = cur.next
node = Node(data)
node.next = cur.next
cur.next = node
def remove(self,data):
cur = self.head
pre = None
while cur != None:
if cur.data == data:
if cur == self.head:
self.head = self.head.next
return
pre.next = cur.next #前节点等于后节点
return
pre = cur
cur = cur.next
def search(self, data):
cur = self.head
while cur != None:
if cur.data == data:
print("数据%f存在于链表中" % cur.data)
return True
cur = cur.next
print("数据不存在于链表中")
return False
if __name__ == '__main__':
chain = chain()
chain.add(0)
chain.traverse()
for i in range(1,9):
chain.append(i)
chain.traverse()
chain.length()
chain.insert(3,100)
chain.traverse()
chain.remove(100)
chain.traverse()
chain.insert(-2,99)
chain.traverse()
chain.insert(100,1000)
chain.traverse()
chain.search(5)
>>>
0-***-
0-***-1-***-2-***-3-***-4-***-5-***-6-***-7-***-8-***-
0-***-1-***-2-***-100-***-3-***-4-***-5-***-6-***-7-***-8-***-
0-***-1-***-2-***-3-***-4-***-5-***-6-***-7-***-8-***-
99-***-0-***-1-***-2-***-3-***-4-***-5-***-6-***-7-***-8-***-
99-***-0-***-1-***-2-***-3-***-4-***-5-***-6-***-7-***-8-***-1000-***-
数据5.000000存在于链表中
单链表优化
class Node:
def __init__(self, elem, next_=None):
self.elem = elem
self.next_ = None
class Llist:
def __init__(self):
self._head = None
def is_empty(self):
return self._head == None #is和== 的差别
def length(self):
cur = self._head
count = 0
while cur != None:
count += 1
cur = cur.next_
return count
def add(self,data): # 头元素的添加
node = Node(data)
node.next_=self._head
self._head = node
def append(self,data):
if self.is_empty():
self.add(data)
else:
cur = self._head
while cur.next_ != None:
cur = cur.next_
node = Node(data)
cur.next_ = node
def insert(self, data, index):
if index <= 0:
self.add(data)
elif index > self.length():
self.append(data)
else:
cur = self._head
for i in range(index-1):
cur = cur.next_
node = Node(data)
node.next_ = cur.next_
cur.next_ = node
def remove_By_data(self,data):# 按照元素值删除
if self.is_empty():
print("None")
else:
cur = self._head
pre = None
while cur != None:
if cur.elem == data:
if cur == self._head: # 头没有前节点
self._head = self._head.next_
return
pre.next_ = cur.next_
pre = cur
cur = cur.next_
def remove_By_index(self,index): #按照位置删除
if index ==0:
self._head = self._head.next_
else:
cur = self._head
pre = None
for i in range(index):
pre = cur
cur = cur.next_
pre.next_ = cur.next_
def delet_all(self):
if self.is_empty():
return
else:
self._head = None
def find_data(self, data):
cur = self._head
count = 0
while cur != None:
if cur.elem == data:
print("数据:%.2f 坐标:%d"%(cur.elem,count))
return
count += 1
cur = cur.next_
def travle(self):
cur = self._head
while cur != None:
print(cur.elem,end="-***-")
cur = cur.next_
print()
if __name__ == '__main__':
chain = Llist()
chain.add(1)
chain.travle()
chain.append(0)
chain.travle()
chain.insert(2,1)
chain.travle()
chain.find_data(2)
chain.insert(3, 1)
chain.find_data(2)
chain.travle()
链表尾端插入优化
前面的单链表实现有一个缺点:尾端加入元素操作时的效率低下,因为每次都是从头端开始查找None指针
现在提出一种可行性设计,其中在表对象中加入一个表尾端引用域,只需要常量时间都能找到尾节点。
class UnorderedList(Llist):
'''单向链表'''
def __init__(self):
# 头结点
self._head = None
# 尾结点(这是保证时间复杂度为O(1)的关键)
# 因为始终实时跟踪尾结点,所以不需要遍历
self.tail = None
def add(self, val):
'''这是向链表头部添加节点的方法'''
temp = Node(val)
temp.next = self._head
self._head = temp
# 如果链表是空的,表示这是第一个添加的节点
# 那么它就应该是尾结点
if self.tail is None:
self.tail = self._head
def append(self, val):
'''这是向链表的尾部添加节点的方法'''
# 如果现在链表还是空的
# 那么append和add做的事情是一样的,所以直接调用add就行了
if self.tail is None:
self.add(val)
# 如果当前链表不为空
# 那么就把新节点拼接到链表的末尾
else:
self.tail.next = Node(val)
self.tail = self.tail.next
循环单链表
class Node(object):
def __init__(self, value):
# 元素域
self.value = value
# 链接域
self.next = None
class CircularLinkedListOneway(object):
def __init__(self, node=None):
# 构造非空链时,让其地址域指向自己
if node:
node.next = node
self.__head = node
def is_empty(self):
# 头节点不为None则不为空
return self.__head == None
def __len__(self):
count = 1
cur = self.__head
if self.is_empty():
return 0
while cur.next != self.__head:
count += 1
cur = cur.next
return count
def traversal(self):
if self.is_empty():
return
cur = self.__head
while cur.next != self.__head:
print(cur.value)
cur = cur.next
# 退出循环时,cur正是尾节点
print(cur.value)
def add(self, value):
"""头插法"""
node = Node(value)
if self.is_empty():
self.__head = node
self.__head.next = self.__head
return
cur = self.__head
while cur.next != self.__head:
cur = cur.next
# 新节点的next指针指向原头节点
node.next = self.__head
# 将新节点指向头节点
self.__head = node
# 尾节点next指针指向新头节点
cur.next = self.__head
def append(self, value):
node = Node(value)
cur = self.__head
if self.is_empty():
self.__head = node
self.__head.next = self.__head
return
while cur.next != self.__head:
cur = cur.next
node.next = cur.next
cur.next = node
def insert(self, pos, value):
if pos <= 0:
self.add(value)
elif pos > len(self) - 1:
self.append(value)
else:
node = Node(value)
cur = self.__head
count = 0
while count < pos - 1:
count += 1
cur = cur.next
node.next = cur.next
cur.next = node
def search(self, value):
if self.is_empty():
return False
cur = self.__head
while cur.next != self.__head:
if cur.value == value:
return True
else:
cur = cur.next
# 别忘了while循环外的尾节点
if cur.value == value:
return True
return False
def remove(self, value):
cur = self.__head
prior = None
if self.is_empty():
return
while cur.next != self.__head:
# 待删除节点如果找到
if cur.value == value:
# 待删除节点在头部
if cur == self.__head:
rear = self.__head
while rear.next != self.__head:
rear = rear.next
self.__head = cur.next
rear.next = self.__head
# 待删除节点在中间
else:
prior.next = cur.next # 这里不是跳出循环的break,而是退出函数的return哦,因为已经处理完毕了
return
# 如果还没找到
else:
prior = cur
cur = cur.next
# 待删除节点在尾部
if cur.value == value:
# 如果链表中只有一个元素,则此时prior为None,Next属性就会报错
# 此时直接使其头部元素为None即可
if cur == self.__head:
self.__head = None
return
prior.next = cur.next
if __name__ == '__main__':
chain = CircularLinkedListOneway()
chain.add(1)
chain.append(2)
chain.traversal()