【代码实战】大话数据结构5:查找部分 Python 代码实现

因本人最近在恶补数据结构,学识经验有限,如有不正之处望读者指正,不胜感激;也望借此平台留下学习笔记以温故而知新。这一篇博客主要是最近刚开始接触大话数据结构一书,写的通俗易懂,很多图表帮忙理解,所以讲随手笔记分享至此,希望对您有所帮助。

查找算法的 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>)

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西瓜情怀总是籽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值