双向链表DoublyLinkedList
-
双向链表和普通链表的不同之处是,双向链表可以通过尾部的tail访问到链表中的元素
-
节点对象除了储存的el,还有perv 和next属性,指向链表的上一个元素和下一个元素
-
对于添加元素时,对链表的head和tail重新赋值的代码需要放在最后,因为需要把之前的head和tail连接到新的元素
-
操作时,需要考虑到当前节点的头和尾,上一节点的头和尾,下一节点的头和尾
class Node:
def __init__(self,el):
self.el = el
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.head = None
self.tail = None
self.__lenth = 0
def append(self,el):
"""
尾部添加新的项"""
new = Node(el)
if self.__lenth == 0:
self.head = new
self.tail = new
else:
self.tail.next = new
new.prev = self.tail
self.tail = new
self.__lenth += 1
def insert(self,position,el):
"""
指定位置插入新的项"""
if position < 0 or position > self.__lenth:
return '失败'
new = Node(el)
if position == 0:
self.head.prev = new
new.next = self.head
self.head = new
elif position == self.__lenth:
self.tail.next = new
new.prev = self.tail
self.tail = new
else:
current = self.head.next
for _ in range(position-1):
current = current.next
current.prev.next = new
new.prev = current.prev
new.next = current
current.prev = new
self.__lenth += 1
def remove(self,el):
"""
移除一项"""
if self.head.el == el:
self.head.next.prev = None
self.head = self.head.next
self.__lenth -= 1
return True
elif self.tail.el == el:
self.tail.prev.next = None
self.tail = self.tail.prev
self.__lenth -= 1
return True
else:
current = self.head.next
for _ in range(self.__lenth-2):
if el == current.el:
current.prev.next = current.next
current.next.prev = current.prev
self.__lenth -= 1
return True
else:
return False
def indexOf(self,el):
"""
返回元素所在链表的位置索引"""
current = self.head
for i in range(self.__lenth):
if el == current.el:
return i
current = current.next
else:
return -1
def removeAt(self,position):
"""
移除指定位置的一项"""
if position>=self.__lenth or position < 0:
return False
if position == 0:
self.head.next.prev = None
self.head = self.head.next
self.__lenth -= 1
return True
elif position == self.__lenth-1:
self.tail.prev.next = None
self.tail = self.tail.prev
self.__lenth -= 1
return True
else:
current = self.head
for _ in range(position-1):
current = current.next
current.prev.next = current.next
current.next.prev = current.prev
self.__lenth -= 1
return True
def isEmpty(self):
"""
判断链表是否为空"""
return not bool(self.__lenth)
def size(self):
"""
返回链表的元素个数"""
return self.__lenth
link = DoublyLinkedList()
# link.append(1)
# link.append(2)
# link.append(3)
# link.insert(0,0)
# link.insert(link.lenth,4)
# link.insert(1,1.5)
# print(link.size())
# link.remove(1.5)
# link.removeAt(1)
# print(link.indexOf(1.5))
# link.removeAt(3)
# print(link.head.el)
# print(link.head.next.el)
# print(link.head.next.next.el)
# print(link.head.next.next.next.el)
# print(link.tail.el)
# print(link.tail.prev.el)
# print(link.tail.prev.prev.el)
# print(link.tail.prev.prev.prev.el)
# print(link.isEmpty())
二叉搜素树Binary Search Tree
- 节点中右左节点,右节点
- 删除节点时需要判断要删除节点的情况,叶子节点,只有一个节点,有两个节点
- 还需要区分删除根节点的情况
- 如果有两个节点,需要找到节点的后继
- 如果后继有子节点,且后继的父节点不是要删除的节点,需要把后继父节点的左节点指向后继的右节点
- 遍历二叉树时,可以假设最简单的情况,或者可以把根节点的左右树看做两个节点,之后递归遍历左右树
class Node:
def __init__(self,el):
self.right = None
self.left = None
self.data = el
class BNT:
def __init__(self):
self.root = None
def insert(self,key):
# 插入新的节点
node = Node(key)
if self.root is None:
self.root = node
else:
current = self.root
parent = None
while current: # 直到当前节点为空
parent = current
if node.data > current.data:
current = current.right
elif node.data < current.data:
current = current.left
if node.data > parent.data: # 当前节点的父节点有一个节点是空 判断之后插入
parent.right = node
elif node.data < parent.data:
parent.left = node
def search(self,key):
# 搜索节点,如果存在,返回True
if key == self.root.data:
return True
else:
current = self.root
while current:
if key == current.data:
return True
elif key > current.data:
current = current.right
elif key < current.data:
current = current.left
return False
def prr(self,node):
print(node.data) # 传入一个节点就答应他的值
if node.left is not None: # 如果不是空,就继续传入函数
self.prr(node.left) # 先左
if node.right is not None:
self.prr(node.right) # 后右
def prrOrderTraverse(self):
# 先序
self.prr(self.root) # 从根节点开始
def in_order(self,node):
'''
假设只有三个节点
11
10 13
print(node.data)
if node.left is not None:
print(node.left.data) # 之后就把左子树 和 右子树 当作一个节点带入函数迭代
if node.right is not None:
print(node.right.data)
'''
# 中序
if node.left is not None: # 如果不为空,就先传入函数
self.in_order(node.left)
print(node.data) # 直到左节点为空,就打印
if node.right is not None: # 之后判断右节点 右树
self.in_order(node.right)
def inOrdefTraverse(self):
# 中序
self.in_order(self.root)
def post(self,node):
if node.left is not None: # 先左树 左节点不为空就传入函数
self.post(node.left)
if node.right is not None: #后右树 右节点不为空 也传入
self.post(node.right)
print(node.data) # 左右节点都为空才打印
def postOrderTraverse(self):
# 后序
self.post(self.root)
def min(self):
# 最小
current = self.root
while current.left:
current = current.left
return current.data
def max(self):
# 最大
current = self.root
while current.right:
current = current.right
return current.data
def remove(self,key):
# 移除
def houji(node):
prev = None
node = node.right # 从右树中找
while node.left:
prev = node
node = node.left
return node,prev
if not self.search(key):
return False
else:
if key == self.root.data: # 如果删除的是根节点
if self.root.left is None and self.root.right is None: # 如果根节点没有子节点
self.root = None
elif self.root.left is None:
self.root = self.root.right
elif self.root.right is None:
self.root = self.root.left
else:
hou_ji,prev = houji(self.root)
if self.root != prev: # 删除的节点不是后继的父节点
prev.left = hou_ji.right # 后继的父节点指向后继的右节点
hou_ji.right = self.root.right
hou_ji.left = self.root.left
self.root = hou_ji
else:
current = self.root # 要删除的节点
parent = None # 父节点
is_left =True
while key != current.data:
if key>current.data:
if current.right is not None:
parent = current
current = current.right
is_left = False
else:
return False
elif key<current.data:
if current.left is not None:
parent = current
current = current.left
else:
return False
# 如果要删除的节点没有子节点
if current.left is None and current.right is None:# 都为空 返回false
if is_left:# 如果为父节点的左节点
parent.left = None
else:
parent.right = None
elif current.left is None and current.right is not None:# 只有右节点
if is_left:# 如果为父节点的左节点
parent.left = current.right
else:
parent.right = current.right
elif current.left is not None and current.right is None:
if is_left:# 如果为父节点的左节点
parent.left = current.left
else:
parent.right = current.left
elif current.left is not None and current.right is not None: # 有两个节点
hou_ji,prev = houji(current) # 找到后继和后继的父节点
if prev != current: # 如果后继的父节点不是要删除的节点
prev.left = hou_ji.right
hou_ji.left = current.left
hou_ji.right = current.right
# hou_ji.right = current.right
if is_left:# 如果为父节点的左节点
parent.left = hou_ji
else:
parent.right = hou_ji
return True
tree = BNT()
tree.insert(11)
# tree.insert(7)
# tree.insert(15)
# tree.insert(5)
# tree.insert(3)
# tree.insert(9)
# tree.insert(8)
# tree.insert(10)
# tree.insert(13)
# tree.insert(12)
# tree.insert(14)
# tree.insert(20)
# tree.insert(18)
# tree.insert(25)
tree.remove(11)
# tree.remove(15)
# tree.remove(20)
tree.prrOrderTraverse()
# tree.inOrdefTraverse()
# tree.postOrderTraverse()
# print(tree.min())
# print(tree.max())
# print(tree.root.data)
# print(tree.root.left.data)
# print(tree.root.left.left.data)
# print(tree.root.left.left.left.data)
# print(tree.root.data)
# print(tree.root.right.data)
# print(tree.root.right.right.data)
# print(tree.root.right.right.right.data)
# print(tree.search(4))
# print(tree.search(26))
# print(tree.search(8))
# print(tree.search(11.5))