因本人最近在恶补数据结构,学识经验有限,如有不正之处望读者指正,不胜感激;也望借此平台留下学习笔记以温故而知新。这一篇博客主要是最近刚开始接触大话数据结构一书,写的通俗易懂,很多图表帮忙理解,所以讲随手笔记分享至此,希望对您有所帮助。
查找算法的 Python 实现
# -*- coding: utf-8 -*-
"""
Created on Thu Jun 25 11:07:01 2020
@author: yx
"""
# 无序表查找
def sequential_search(L, key):
'''
函数功能:顺序表查找(无序表查找)
基本思想:在数组中查找key值
参数 L:待查找列表
参数 key:待查找数值
返回 result:查找到的数据在列表下标
'''
n = len(L)
i = 0
result = []
while(i < n):
if L[i] == key:
result.append(i)
i += 1
if len(result) == 0:
result = False
return result
# 有序表查找
def binary_search(L, key):
'''
函数功能:二分顺序表查找
基本思想:二分法循环折半查找时
参数 L:待查找列表
参数 key:待查找数值
返回 result:查找到的数据在列表下标
'''
n = len(L)
low = 0
high = n-1
alpha = 1 /2 # 二分查找系数
while(low < high):
mid = low + int( alpha * (high - low))
if key > L[mid]:
low = mid + 1
elif key < L[mid]:
high = mid - 1
else:
result = mid
return result
return False
# 索引查找 - 倒排索引
def reverse_index_srearch(D, key):
'''
函数功能:倒排索引
参数 D:待查找字典
参数 key:待查找索引
返回 result:查找到的结果
'''
values = []
for k, v in D.items():
values.extend(v)
values_set = set(values)
reverse_index = {}
# key,value倒排
for value in values_set:
reverse_index[value] = []
for k, v in D.items():
if value in v:
reverse_index[value].append(k)
# 索引查找并返回
for k, v in reverse_index.items():
if k == key:
result = v
return result
# 二叉查找树(二叉排序树)
class node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def create_tree(T, data):
if T is None:
T = node(data)
else:
if (data < T.data):
T.left = create_tree(T.left, data)
elif data > T.data:
T.right = create_tree(T.right, data)
return T
def cerate_binary_tree(binary_tree):
T = None
for i in binary_tree:
T = create_tree(T, i)
return T
def binary_sort_tree_search(T, key):
'''
函数功能:二叉排序树
参数 T:待查找树
参数 key:
'''
if T is None:
return
if T.data is key:
return T.data, T.left, T.right
if T.data < key:
return binary_sort_tree_search(T.right, key)
else:
return binary_sort_tree_search(T.left, key)
# 二叉平衡树
class Node(object):
def __init__(self, key, value, left=None, right=None):
self.key = key # 存储索引数值
self.value = value # 存储具体的数
self.left = left # 左节点
self.right = right # 右节点
self.is_delete = False # 删除标记, True为被删除,不会被搜索到
self.bf = 0 # 平衡差,为左子树层级减去右子树层级,介于[-1,1]为合法值
class BalancedBinaryTree(object):
"""
最小不平衡树 距离插入节点处最近的一个bf为-1/1的节点,
新插入的节点若插入后引起树的不平衡,只要更改此节点为平衡树,则整个树就会平衡
"""
def __init__(self):
self.root = None
@staticmethod
def left_whirl(node):
"""
左旋
当node值为-2的时候可以执行此操作使其节点值为0,node为最小不平衡树的根节点
:param node:
:return:
"""
node.bf = node.right.bf = 0
node_right = node.right
node.right = node.right.left
node_right.left = node
return node_right
@staticmethod
def right_whirl(node):
"""
右旋
当node值为2的时候可以执行此操作使其节点值为0,node为最小不平衡树的根节点
:param node:
:return:
"""
node.bf = node.left.bf = 0
node_left = node.left
node.left = node.left.right
node_left.right = node
return node_left
@staticmethod
def left_right_whirl(node):
"""
左右旋,先左旋子节点,再右旋node节点
:param node:
:return:
"""
node_b = node.left
node_c = node_b.right
node.left = node_c.right
node_b.right = node_c.left
node_c.left = node_b
node_c.right = node
if node_c.bf == 0:
node.bf = node_b.bf = 0
elif node_c.bf == 1:
node.bf = -1
node_b.bf = 0
else:
node.bf = 0
node_b.bf = 1
node_c.bf = 0
return node_c
@staticmethod
def right_left_whirl(node):
"""
右左旋,先右旋子节点,再左旋node节点
:param node:
:return:
"""
node_b = node.right
node_c = node_b.left
node_b.left = node_c.right
node.right = node_c.left
node_c.right = node_b
node_c.left = node
if node_c.bf == 0:
node.bf = node_b.bf = 0
elif node_c.bf == 1:
node.bf = 0
node_b.bf = -1
else:
node.bf = 1
node_b.bf = 0
node_c.bf = 0
return node_c
def insert(self, key, value):
"""
插入数据
1 寻找插入点,并记录下距离该插入点的最小非平衡子树及其父子树
2 修改最小非平衡子树到插入点的bf
3 进行调整
:param key:
:param value:
:return:
"""
if not self.root:
self.root = Node(key, value)
return
# a:最小非平衡树节点 p:插入点
a, p = self.root, self.root
# a与p节点的父节点,a_father用以链接旋转后的节点, p_father用以在循环时给a_father赋值
a_father, p_father = None, None
# 寻找插入点,并记录下距离该插入点的最小非平衡子树(a) 父子树(a_father) 插入点(p)
while p:
if p.key == key:
# 直接修改
p.value = value
return
if p.bf != 0:
a_father, a = p_father, p
p_father = p
if key > p.key:
p = p.right
else:
p = p.left
# 插入点
node = Node(key, value)
if key > p_father.key:
p_father.right = node
else:
p_father.left = node
# 修改从a到插入点p的bf值
ta = a
while ta:
if ta.key == key:
break
elif key > ta.key:
ta.bf -= 1
ta = ta.right
else:
ta.bf += 1
ta = ta.left
# 判断新节点是插入在a子节点的左边(True)还是右边(False)
if a.key > key:
p_pos = a.left.key > key
else:
p_pos = a.right.key > key
# 旋转修改
if a.bf > 1:
# 新节点插入到了a节点的左边并导致了不平衡,此时需要判断是要进行右旋转还是左右旋转
if p_pos:
a = BalancedBinaryTree.right_whirl(a)
else:
a = BalancedBinaryTree.left_right_whirl(a)
elif a.bf < -1:
# 新节点插入到了a节点的右边并导致了不平衡,此时需要判断是要进行左旋转还是右左旋转
if p_pos:
a = BalancedBinaryTree.right_left_whirl(a)
else:
a = BalancedBinaryTree.left_whirl(a)
# 将调整后的a节点加入到a_father节点中
if a_father:
if a_father.key > key:
a_father.left = a
else:
a_father.right = a
else:
self.root = a
def _search(self, key):
p = self.root
while p:
if p.key == key:
if p.is_delete:
p = None
break
elif p.key > key:
p = p.left
else:
p = p.right
else:
return None
return p
def search(self, key):
res = self._search(key)
if res:
return res.value
return None
if __name__ == "__main__":
key = 4
L = list([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
D = {'a': [1, 2, 3],
'b': [2, 3, 4],
'c': [1, 4, 5],
'd': [1, 3, 9]}
binary_tree = list([6, 4, 8, 3, 5, 7, 9])
BT = cerate_binary_tree(binary_tree)
a = [(1, 'a'), (2, 'g'), (3, 'h'), (4, 'b'), (5, 'd'), (3.5, 'e')]
# 平衡树查找
bbt = BalancedBinaryTree()
for item in a:
bbt.insert(item[0], item[1])
print('平衡树查找结果', bbt.search(1))
# 无序表查找
sequential_search_result = sequential_search(L, key)
print('无序表查找结果', sequential_search_result)
# 有序表查找
binary_search_result = binary_search(L, key)
print('有序表二分查找', binary_search_result)
# 索引查找 - 倒排索引
reverse_index_srearch_result = reverse_index_srearch(D, key)
print('倒排索引查找结果', reverse_index_srearch_result)
# 二叉查找树
binary_sort_tree_search_result = binary_sort_tree_search(BT, key)
print('二叉查找树查找结果', binary_sort_tree_search_result)
查找结果:
平衡树查找结果 a
无序表查找结果 [3]
有序表二分查找 False
倒排索引查找结果 ['b', 'c']
二叉查找树查找结果 (4, <__main__.node object at 0x000001F1868E79B0>, <__main__.node object at 0x000001F1868E76A0>)