首页

▼ 算法合集

▼ 加密算法

▼ 凯撒密码

凯撒密码

▼ Hill密码算法

Hill密码算法

▼ 多项式哈希算法

多项式哈希算法

▼ Rail Fence Cipher

Rail Fence Cipher

▼ Graph算法

▼ 关节点

关节点

▼ Bellman-Ford算法

Bellman-Ford算法

▼ 广度优先搜索

广度优先搜索

▼ GraphBridges

桥接模式

▼ 深度优先搜索

深度优先搜索

▼ 检测循环

检测循环

▼ Dijkstra算法

Dijkstra算法

▼ Eulerian Path

欧拉路径

▼ Floyd-Warshall算法

Floyd-Warshall算法

▼ HamiltonianCycle

Hamiltonian Cycle

▼ Kruskal算法

Kruskal算法

▼ Prim算法

Prim算法

▼ 强连通分量

强连通分量

▼ 拓扑排序

拓扑排序

▼ Travelling Salesman Problem

Travelling Salesman

▼ 图像处理算法

▼ Seam Carving算法

内容感知缩放算法

▼ 链表

▼ 反向遍历

反向遍历

▼ GraphTraversal

GraphTraversal

▼ 数学算法

▼ 二进制浮点数

BinaryFloatingPoint

▼ 位操作

位操作算法

▼ 复数

复数

▼ 欧几里得算法

Euclidean Algorithm

▼ Euclidean Distance

欧几里得距离

▼ 阶乘算法

阶乘算法

▼ 快速幂算法

快速幂算法

▼ Fibonacci数列

斐波那契数列

▼ 傅里叶变换

Fourier变换

▼ Horner法

霍纳法则

▼ 整数划分

整数划分

▼ 判断是否为2的幂

判断是否为2的幂

▼ 最小公倍数

最小公倍数

▼ Liu Hui

Liu Hui

▼ 矩阵

Matrix

▼ Pascal三角形

Pascal三角形

▼ Primality Test

素数测试

▼ 质因数

质因数

▼ 弧度计算

弧度计算

▼ 埃拉托色尼筛法

埃拉托色尼筛法

▼ SquareRoot

SquareRoot

▼ MachineLearning

▼ K均值算法

K均值算法

▼ K近邻算法

K近邻算法

▼ 搜索算法

▼ 二分查找算法

二分查找

▼ 插值搜索算法

插值搜索算法

▼ 跳跃搜索算法

跳跃搜索算法

▼ 线性搜索

线性搜索算法

▼ 集合

▼ 笛卡尔积

笛卡尔积

▼ 组合总和

组合总和

▼ 组合算法

组合算法

▼ Fisher-Yates洗牌算法

Fisher-Yates洗牌算法

▼ 背包问题

背包问题

▼ 最长公共子序列

最长公共子序列

▼ 最长递增子序列

最长递增子序列

▼ 最大子数组

最大子数组

▼ 排列组合

排列组合

▼ 幂集

幂集算法

▼ 最短公共超序列

最短公共超序列

▼ Sorting Algorithms

▼ 冒泡排序

冒泡排序

▼ 桶排序算法

桶排序算法

▼ 计数排序算法

计数排序

▼ 堆排序算法

堆排序

▼ 插入排序

插入排序

▼ 归并排序

归并排序

▼ 快速排序算法

快速排序算法

▼ 基数排序

基数排序

▼ 选择排序算法

选择排序算法

▼ 希尔排序

希尔排序

▼ 统计学

▼ 加权随机

加权随机算法

▼ 字符串算法

▼ Hamming距离

Hamming距离

▼ KnuthMorrisPratt算法

Knuth-Morris-Pratt算法

▼ LevenshteinDistance

Levenshtein距离

▼ 最长公共子串

最长公共子串

▼ 回文检测算法

回文检测算法

▼ Rabin-Karp算法

Rabin-Karp算法

▼ 正则表达式匹配

正则表达式匹配

▼ Z算法

Z算法

▼ Tree Data Structure

▼ 广度优先搜索

广度优先搜索

▼ 深度优先搜索

深度优先搜索

▼ 未分类

▼ 最佳买卖股票时机

最佳买卖股票时机

▼ 汉诺塔算法

HanoiTower

▼ 跳跃游戏算法

跳跃游戏

▼ KnightTour

骑士巡逻

▼ N皇后问题

N皇后问题

▼ 雨水收集

雨水收集

▼ 递归楼梯问题

递归楼梯问题

▼ 方阵旋转

方阵旋转

▼ 独特路径

UniquePaths

▼ 数据结构

▼ BloomFilter算法

布隆过滤器

▼ 不相交集数据结构

Disjoint Set

▼ 双向链表

双向链表

▼ Graph

Graph算法

▼ 哈希表

哈希表

▼ Heap数据结构

Heap数据结构

▼ 链表

链表

▼ LRU缓存

LRU缓存

▼ 优先队列

优先队列

▼ 队列

队列

▼ 栈结构

栈结构

▼ Tree Data Structure

树结构

▼ AVL树

AVL树

▼ 二叉搜索树

二叉搜索树

▼ Fenwick树

Fenwick树

▼ 红黑树

红黑树

▼ 线段树

SegmentTree

▼ Trie数据结构

Trie数据结构

二叉搜索树

在其他语言中阅读: 葡萄牙语

在计算机科学中,二叉搜索树(BST),有时称为有序或排序二叉树,是一种特殊的容器: 用于存储“项目”(如数字、名称等)的内存数据结构。它们允许快速查找、添加和删除项目,并且可以用来实现动态项目集合,或者通过键查找项目的查找表(例如,通过姓名查找人的电话号码)。

二叉搜索树保持其键的排序顺序,以便查找和其他操作可以使用二分搜索原则: 当在树中查找键(或插入新键)时,它们从根到叶遍历树,与存储在树节点中的键进行比较,并根据比较结果决定继续在左子树还是右子树上搜索。平均而言,这意味着每次比较可以让操作跳过大约一半的树,因此每个查找、插入或删除操作的时间与树中存储的项目数量的对数成比例。这比在(未排序的)数组中按键查找项目所需的线性时间要好得多,但比哈希表上的相应操作要慢。

一个大小为9,深度为3的二叉搜索树,根上有8个节点。 叶子节点未绘制。

前缀树

使用okso.app制作*

基本操作的伪代码

插入

insert(value)
  预处理:value已通过自定义类型检查,类型为T
  后处理:value已放置在树中的正确位置
  如果root为空
    root←节点(value)
  否则
    insertNode(root, value)
  结束如果
end insert
insertNode(current, value)
  预处理:current是从哪里开始节点
  后处理:value已放置在树中的正确位置
  如果value<当前.value
    如果当前.left为空
      当前.left←节点(value)
    否则
      插入Node(current.left, value)
    结束如果
  否则
    如果当前.right为空
      当前.right←节点(value)
    否则
      插入Node(current.right, value)
    结束如果
  结束如果
end insertNode

查找

contains(root, value)
  预处理:root是树的根节点,value是我们想要定位的值
  后处理:value要么找到,要么找不到
  如果root为空
    返回false
  结束如果
  如果root.value=value
    返回true
  否则如果value<root.value
    返回contains(root.left, value)
  否则
    返回contains(root.right, value)
  结束如果
end contains

删除

remove(value)
  预处理:value是要删除的节点的值,root是BST的节点
      count是BST中项目的数量
  后处理:如果找到值为value的节点,则删除它并返回true,否则返回false
  nodeToRemove←findNode(value)
  如果nodeToRemove=ø
    返回false
  结束如果
  parent←findParent(value)
  如果count=1
    root←ø
  否则如果nodeToRemove.left=ø且nodeToRemove.right=ø
    如果nodeToRemove.value<parent.value
      parent.left←nodeToRemove.right
    否则
      parent.right←nodeToRemove.right
    结束如果
  否则如果nodeToRemove.left≠ø且nodeToRemove.right≠ø
    next←nodeToRemove.right
    while next.left≠ø
      next←next.left
    结束循环
    如果next≠nodeToRemove.right
      remove(next.value)
      nodeToRemove.value←next.value
    否则
      nodeToRemove.value←next.value
      nodeToRemove.right←nodeToRemove.right.right
    结束如果
  否则
    如果nodeToRemove.left=ø
      next←nodeToRemove.right
    否则
      next←nodeToRemove.left
    结束如果
    如果root=nodeToRemove
      root=next
    否则如果parent.left=nodeToRemove
      parent.left=next
    否则如果parent.right=nodeToRemove
      parent.right=next
    结束如果
  结束如果
  count←count-1
  返回true
end remove

查找节点的父节点

findParent(value, root)
  预处理:value是我们要找的节点的值,root是BST的根节点且不等于ø
  后处理:如果找到value的父节点,则返回父节点的引用;否则返回ø
  如果value=root.value
    返回ø
  结束如果
  如果value<root.value
    如果root.left=ø
      返回ø
    否则如果root.left.value=value
      返回root
    否则
      返回findParent(value, root.left)
    结束如果
  否则
    如果root.right=ø
      返回ø
    否则如果root.right.value=value
      返回root
    否则
      返回findParent(value, root.right)
    结束如果
  结束如果
end findParent

查找节点

findNode(root, value)
  预处理:value是我们要找的节点的值,root是BST的根节点
  后处理:如果找到value的节点,则返回该节点的引用;否则返回ø
  如果root=ø
    返回ø
  结束如果
  如果root.value=value
    返回root
  否则如果value<root.value
    返回findNode(root.left, value)
  否则
    返回findNode(root.right, value)
  结束如果
end findNode

查找最小值

findMin(root)
  预处理:root是BST的根节点
    root=ø
  后处理:BST中最小值已找到
  如果root.left=ø
    返回root.value
  结束如果
  findMin(root.left)
end findMin

查找最大值

findMax(root)
  预处理:root是BST的根节点
    root=ø
  后处理:BST中最大值已找到
  如果root.right=ø
    返回root.value
  结束如果
  findMax(root.right)
end findMax

遍历

中序遍历

inorder(root)
  预处理:root是BST的根节点
  后处理:BST中的节点已按中序遍历
  如果root≠ø
    inorder(root.left)
    输出root.value
    inorder(root.right)
  结束如果
end inorder

前序遍历

preorder(root)
  预处理:root是BST的根节点
  后处理:BST中的节点已按前序遍历
  如果root≠ø
    输出root.value
    preorder(root.left)
    preorder(root.right)
  结束如果
end preorder

后序遍历

后序遍历(root)
  预处理:root是二叉搜索树(BST)的根节点
  后处理:二叉搜索树中的节点已按后序遍历顺序访问
  如果根节点不为空
    后序遍历(root的左子树)
    后序遍历(root的右子树)
    输出root的值
  结束条件
end 后序遍历

复杂度分析

时间复杂度

访问 搜索 插入 删除
O(log(n)) O(log(n)) O(log(n)) O(log(n))

空间复杂度

O(n)

参考资料