IT评测·应用市场-qidao123.com

标题: 常用查找算法整理(顺序查找、二分查找、哈希查找、二叉排序树查找、平衡二 [打印本页]

作者: 守听    时间: 2025-2-16 21:23
标题: 常用查找算法整理(顺序查找、二分查找、哈希查找、二叉排序树查找、平衡二
常用的查找算法:
顺序查找

根本概念
顺序查找,也称为线性查找,是在一个数据聚会集从第一个元素开始,逐个比较元素,直到找到目标元素或遍历完备个聚集为止的查找方法。它实用于无序的线性表,也可用于有序的线性表。
算法实现

  1. def sequential_search(lst, target):
  2.     for i, element in enumerate(lst):
  3.         if element == target:
  4.             return i
  5.     return -1
  6. # 测试
  7. lst = [10, 20, 30, 40, 50]
  8. target = 30
  9. print(sequential_search(lst, target))  
复制代码
时间复杂度

优缺点

实用场景

二分查找

根本原理
二分查找也称为折半查找,其根本思想是:每次将待查找区间缩小为原来的一半,通过不断比较中间元素与目标元素的巨细关系,来确定下一步的查找区间,直到找到目标元素或者确定目标元素不存在为止。
算法实现

Python代码示例
  1. def binary_search(lst, target):
  2.     left, right = 0, len(lst) - 1
  3.     while left <= right:
  4.         mid = left + (right - left) // 2
  5.         if lst[mid] == target:
  6.             return mid
  7.         elif lst[mid] > target:
  8.             right = mid - 1
  9.         else:
  10.             left = mid + 1
  11.     return -1
  12. # 测试
  13. lst = [10, 20, 30, 40, 50]
  14. target = 30
  15. print(binary_search(lst, target))  
复制代码
时间复杂度

优缺点

实用场景

哈希查找

根本原理

解决辩说的方法

算法实现
以下是使用链地点法实现哈希查找的Python代码示例:
  1. class HashTable:
  2.     def __init__(self, size):
  3.         self.size = size
  4.         self.table = [[] for _ in range(size)]
  5.     def hash_function(self, key):
  6.         return key % self.size
  7.     def insert(self, key, value):
  8.         hash_value = self.hash_function(key)
  9.         self.table[hash_value].append((key, value))
  10.     def search(self, key):
  11.         hash_value = self.hash_function(key)
  12.         for k, v in self.table[hash_value]:
  13.             if k == key:
  14.                 return v
  15.         return None
  16. # 测试
  17. hash_table = HashTable(10)
  18. hash_table.insert(1, 'apple')
  19. hash_table.insert(11, 'banana')
  20. print(hash_table.search(11))  
复制代码
时间复杂度

优缺点

实用场景

树查找

二叉排序树

定义
二叉排序树(Binary Search Tree,BST),也称为二叉查找树、二叉搜索树,它是一种特殊的二叉树。对于树中的恣意一个节点,都满足以下性质:

示例
以下是一个简单的二叉排序树示例,树中节点的值分别为 50、30、70、20、40、60、80:
  1.         50
  2.        /  \
  3.      30    70
  4.     /  \   / \
  5.   20   40 60  80
复制代码
在这个二叉排序树中,节点 50 的左子树(30、20、40)中的所有节点值都小于 50,右子树(70、60、80)中的所有节点值都大于 50。并且节点 30 的左子树(20)节点值小于 30,右子树(40)节点值大于 30,以此类推。
插入操纵
插入新节点时,从根节点开始比较。如果新节点的值小于当前节点的值,则在左子树中继续查找插入位置;如果新节点的值大于当前节点的值,则在右子树中继续查找插入位置,直到找到一个空位置插入新节点。
例如,要在上述二叉排序树中插入节点 35,从根节点 50 开始,35 小于 50,进入左子树;35 大于 30,进入 30 的右子树;此时 30 的右子树节点 40 存在,35 小于 40,进入 40 的左子树,发现为空,将 35 插入该位置。
删除操纵
删除操纵相对复杂,需要分三种环境:

二叉排序树搜索
搜索过程
在二叉排序树中搜索一个特定值的过程如下:
代码实现(Python)
  1. class TreeNode:
  2.     def __init__(self, val=0, left=None, right=None):
  3.         self.val = val
  4.         self.left = left
  5.         self.right = right
  6. def searchBST(root, val):
  7.     if root is None or root.val == val:
  8.         return root
  9.     if val < root.val:
  10.         return searchBST(root.left, val)
  11.     return searchBST(root.right, val)
  12. # 构建示例二叉排序树
  13. root = TreeNode(50)
  14. root.left = TreeNode(30)
  15. root.right = TreeNode(70)
  16. root.left.left = TreeNode(20)
  17. root.left.right = TreeNode(40)
  18. root.right.left = TreeNode(60)
  19. root.right.right = TreeNode(80)
  20. # 搜索值为 60 的节点
  21. result = searchBST(root, 60)
  22. if result:
  23.     print(f"找到了值为 {result.val} 的节点")
  24. else:
  25.     print("未找到该节点")
复制代码
复杂度分析

应用场景
二叉排序树实用于需要频仍进行插入、删除和搜索操纵的场景,并且数据聚集的规模适中。例如,在一些小型的数据库系统中,用于快速查找特定记载;在编程语言的符号表管理中,用于存储和查找变量名及其相干信息等。
平衡二叉树

定义
平衡二叉树(AVL树)是一种自平衡的二叉搜索树。它满足二叉搜索树的根天性质:对于树中的恣意节点,其左子树中所有节点的值都小于该节点的值,右子树中所有节点的值都大于该节点的值。同时,AVL树还额外要求每个节点的左右子树的高度差(平衡因子)的绝对值不超过 1。平衡因子定义为该节点的左子树高度减去右子树高度。
平衡的重要性
通过保持树的平衡,AVL树可以或许保证在进行插入、删除和查找操纵时的时间复杂度始终为                                    O                         (                         l                         o                         g                         n                         )                              O(log n)                  O(logn),此中                                    n                              n                  n 是树中节点的数目。如果不进行平衡操纵,二叉搜索树可能会退化为链表,此时这些操纵的时间复杂度会变为                                    O                         (                         n                         )                              O(n)                  O(n)。
平衡二叉树查找过程
平衡二叉树的查找过程与普通二叉搜索树的查找过程根本同等:
示例代码(Python 实现)
  1. # 定义 AVL 树的节点类
  2. class TreeNode:
  3.     def __init__(self, key):
  4.         self.key = key
  5.         self.left = None
  6.         self.right = None
  7.         self.height = 1  # 节点的高度,初始为 1
  8. # 定义 AVL 树类
  9. class AVLTree:
  10.     # 获取节点的高度
  11.     def get_height(self, node):
  12.         if not node:
  13.             return 0
  14.         return node.height
  15.     # 获取节点的平衡因子
  16.     def get_balance(self, node):
  17.         if not node:
  18.             return 0
  19.         return self.get_height(node.left) - self.get_height(node.right)
  20.     # 右旋操作
  21.     def right_rotate(self, y):
  22.         x = y.left
  23.         T2 = x.right
  24.         x.right = y
  25.         y.left = T2
  26.         y.height = max(self.get_height(y.left), self.get_height(y.right)) + 1
  27.         x.height = max(self.get_height(x.left), self.get_height(x.right)) + 1
  28.         return x
  29.     # 左旋操作
  30.     def left_rotate(self, x):
  31.         y = x.right
  32.         T2 = y.left
  33.         y.left = x
  34.         x.right = T2
  35.         x.height = max(self.get_height(x.left), self.get_height(x.right)) + 1
  36.         y.height = max(self.get_height(y.left), self.get_height(y.right)) + 1
  37.         return y
  38.     # 插入节点
  39.     def insert(self, root, key):
  40.         if not root:
  41.             return TreeNode(key)
  42.         elif key < root.key:
  43.             root.left = self.insert(root.left, key)
  44.         else:
  45.             root.right = self.insert(root.right, key)
  46.         root.height = 1 + max(self.get_height(root.left), self.get_height(root.right))
  47.         balance = self.get_balance(root)
  48.         # 左左情况
  49.         if balance > 1 and key < root.left.key:
  50.             return self.right_rotate(root)
  51.         # 右右情况
  52.         if balance < -1 and key > root.right.key:
  53.             return self.left_rotate(root)
  54.         # 左右情况
  55.         if balance > 1 and key > root.left.key:
  56.             root.left = self.left_rotate(root.left)
  57.             return self.right_rotate(root)
  58.         # 右左情况
  59.         if balance < -1 and key < root.right.key:
  60.             root.right = self.right_rotate(root.right)
  61.             return self.left_rotate(root)
  62.         return root
  63.     # 查找节点
  64.     def search(self, root, key):
  65.         if root is None or root.key == key:
  66.             return root
  67.         if key < root.key:
  68.             return self.search(root.left, key)
  69.         return self.search(root.right, key)
  70. # 测试代码
  71. if __name__ == "__main__":
  72.     avl_tree = AVLTree()
  73.     root = None
  74.     keys = [9, 5, 10, 0, 6, 11, -1, 1, 2]
  75.     for key in keys:
  76.         root = avl_tree.insert(root, key)
  77.     target = 6
  78.     result = avl_tree.search(root, target)
  79.     if result:
  80.         print(f"找到了节点: {result.key}")
  81.     else:
  82.         print(f"未找到节点: {target}")
复制代码
代码表明
通过这种方式,我们可以在平衡二叉树中高效地进行查找操纵。
复杂度分析

空间复杂度

适合使用的场景

红黑树

定义
红黑树是一种自平衡的二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是红色或黑色。通过对任何一条从根到叶子的路径上各个节点着色方式的限定,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。红黑树必须满足以下五个性质:
示例
以下是一个简单的红黑树示例(为方便表示,这里用括号内的 R 表示红色节点,B 表示黑色节点):
  1.         (50B)
  2.        /      \
  3.     (30R)      (70R)
  4.    /    \      /    \
  5. (20B)  (40B) (60B)  (80B)
复制代码
在这个红黑树中,根节点 50 是黑色,红色节点 30 和 70 的子节点都是黑色,并且从每个节点到其所有子女叶节点的简单路径上黑色节点的数目相同。
红黑树查找
查找过程
红黑树的查找过程与普通二叉搜索树的查找过程根本相同,具体步骤如下:
代码实现(Python)

  1. class TreeNode:
  2.     def __init__(self, val=0, color='R', left=None, right=None):
  3.         self.val = val
  4.         self.color = color
  5.         self.left = left
  6.         self.right = right
  7. def searchRedBlackTree(root, val):
  8.     if root is None or root.val == val:
  9.         return root
  10.     if val < root.val:
  11.         return searchRedBlackTree(root.left, val)
  12.     return searchRedBlackTree(root.right, val)
  13. # 构建简单红黑树示例(这里只是简单构建,未完整体现插入调整逻辑)
  14. root = TreeNode(50, 'B')
  15. root.left = TreeNode(30, 'R')
  16. root.right = TreeNode(70, 'R')
  17. root.left.left = TreeNode(20, 'B')
  18. root.left.right = TreeNode(40, 'B')
  19. root.right.left = TreeNode(60, 'B')
  20. root.right.right = TreeNode(80, 'B')
  21. # 查找值为 60 的节点
  22. result = searchRedBlackTree(root, 60)
  23. if result:
  24.     print(f"找到了值为 {result.val} 的节点")
  25. else:
  26.     print("未找到该节点")
复制代码
复杂度分析

应用场景
红黑树在很多领域都有广泛的应用,以下是一些常见的场景:

B 树和B+数查询

B树

定义
B 树是一种自平衡的多路搜索树,它可以或许保持数据有序,并且答应在对数时间内进行插入、删除和查找操纵。B 树的每个节点可以有多个子节点(通常大于 2),并且所有叶子节点都在同一层。一个 m 阶的 B 树需要满足以下条件:

示例
下面是一个 3 阶 B 树的简单示例:
  1.           [30, 60]
  2.         /    |    \
  3.     [10, 20] [40, 50] [70, 80]
复制代码
在这个 3 阶 B 树中,根节点包含两个键值 30 和 60,有三个子节点。每个子节点包含两个键值,并且键值是有序排列的。
B 树查找过程
代码实现(Python 伪代码)
  1. class BTreeNode:
  2.     def __init__(self, is_leaf=False):
  3.         self.is_leaf = is_leaf
  4.         self.keys = []
  5.         self.child = []
  6. class BTree:
  7.     def __init__(self, m):
  8.         self.root = BTreeNode(is_leaf=True)
  9.         self.m = m
  10.     def search(self, key):
  11.         return self._search(self.root, key)
  12.     def _search(self, node, key):
  13.         i = 0
  14.         while i < len(node.keys) and key > node.keys[i]:
  15.             i += 1
  16.         if i < len(node.keys) and key == node.keys[i]:
  17.             return node
  18.         if node.is_leaf:
  19.             return None
  20.         return self._search(node.child[i], key)
  21. # 示例使用
  22. b_tree = BTree(3)
  23. # 这里省略插入节点的代码
  24. result = b_tree.search(40)
  25. if result:
  26.     print("找到了键值 40")
  27. else:
  28.     print("未找到键值 40")
复制代码
复杂度分析

应用场景
B 树常用于文件系统和数据库系统中,由于它可以有用减少磁盘 I/O 次数。在这些系统中,数据通常存储在磁盘上,磁盘 I/O 操纵的时间开销较大,B 树的多路特性使得每次磁盘 I/O 可以读取或写入多个键值,从而提高了系统的性能。
B + 树

定义
B + 树是 B 树的一种变体,它与 B 树的主要区别在于:

示例
以下是一个简单的 B + 树示例:
  1.          [30, 60]
  2.         /      \
  3.     [10, 20]    [40, 50, 70, 80]
  4.     |         /   |   \
  5.     10       40   50   70 - 80 (叶子节点相连)
复制代码
在这个 B + 树中,非叶子节点只包含索引键值 30 和 60,所有的数据(10、20、40、50、70、80)都存储在叶子节点中,并且叶子节点通过指针形成了有序链表。
B + 树查找过程

代码实现(Python 伪代码)
  1. class BPlusTreeNode:
  2.     def __init__(self, is_leaf=False):
  3.         self.is_leaf = is_leaf
  4.         self.keys = []
  5.         self.child = []
  6.         self.next = None
  7. class BPlusTree:
  8.     def __init__(self, m):
  9.         self.root = BPlusTreeNode(is_leaf=True)
  10.         self.m = m
  11.     def search(self, key):
  12.         node = self.root
  13.         while not node.is_leaf:
  14.             i = 0
  15.             while i < len(node.keys) and key > node.keys[i]:
  16.                 i += 1
  17.             node = node.child[i]
  18.         for k in node.keys:
  19.             if k == key:
  20.                 return True
  21.         return False
  22. # 示例使用
  23. b_plus_tree = BPlusTree(3)
  24. # 这里省略插入节点的代码
  25. result = b_plus_tree.search(50)
  26. if result:
  27.     print("找到了键值 50")
  28. else:
  29.     print("未找到键值 50")
复制代码
复杂度分析

应用场景
B + 树在数据库系统中应用广泛,如 MySQL 的 InnoDB 存储引擎默认使用 B + 树作为索引布局。由于 B + 树的布局非常适合范围查询,并且由于所有数据都存储在叶子节点,使得数据库的插入、删除和查找操纵更加高效和稳固。同时,叶子节点的有序链表布局也方便进行顺序访问,提高了数据的读取效率。
分块查找

也称为索引顺序查找,它是一种介于顺序查找和二分查找之间的查找方法。以下从根本思想、实现步骤、复杂度分析、优缺点和实用场景等方面具体介绍:
根本思想
分块查找将一个线性表分成若干个块,每个块内的元素可以是无序的,但块与块之间是有序的,即后一个块中所有元素的值都大于前一个块中所有元素的值。同时,还需要创建一个索引表,索引表中记载了每个块的最大关键字以及该块在原线性表中的起始位置,索引表是按关键字有序排列的。
实现步骤
分块查找主要分为两步:
示例及代码实现
假设我们有一个线性表 [22, 12, 13, 8, 9, 20, 33, 42, 44, 38, 24, 48],将其分成 3 个块,每个块有 4 个元素。
索引表为 [(22, 0), (44, 4), (48, 8)],此中每个元组的第一个元素是块的最大关键字,第二个元素是块在原线性表中的起始位置。
以下是 Python 代码实现:
  1. def block_search(arr, index_table, target):
  2.     # 第一步:在索引表中确定所在块
  3.     block_index = -1
  4.     for i in range(len(index_table)):
  5.         if target <= index_table[i][0]:
  6.             block_index = i
  7.             break
  8.     if block_index == -1:
  9.         return -1
  10.     # 第二步:在块内进行顺序查找
  11.     start = index_table[block_index][1]
  12.     if block_index == len(index_table) - 1:
  13.         end = len(arr)
  14.     else:
  15.         end = index_table[block_index + 1][1]
  16.     for i in range(start, end):
  17.         if arr[i] == target:
  18.             return i
  19.     return -1
  20. # 线性表
  21. arr = [22, 12, 13, 8, 9, 20, 33, 42, 44, 38, 24, 48]
  22. # 索引表
  23. index_table = [(22, 0), (44, 4), (48, 8)]
  24. target = 24
  25. result = block_search(arr, index_table, target)
  26. if result != -1:
  27.     print(f"元素 {target} 在数组中的索引是 {result}")
  28. else:
  29.     print(f"未找到元素 {target}")
复制代码
复杂度分析

优缺点

实用场景

斐波那契查找和插值查找在特定场景下有其独特的上风,但整体而言,它们不如顺序查找、二分查找等方法常用,以下为你具体分析:
斐波那契查找和插值查找

斐波那契查找


插值查找



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4