V

算法可视化

ZHEN
分享到微博分享到 XGitHub 仓库个人主页
学习工具算法复杂度速查算法学习路径
数据结构数组链表栈队列树堆哈希表图字典树并查集LRU 缓存跳表线段树B+ 树布隆过滤器树状数组
经典排序算法冒泡排序鸡尾酒排序双调排序选择排序插入排序二分插入排序希尔排序归并排序自顶向下归并快速排序三路快排双轴快排堆排序计数排序基数排序桶排序
图算法Dijkstra 最短路Kruskal 最小生成树Prim 最小生成树Bellman-Ford 最短路拓扑排序Floyd 多源最短路强连通分量2-SAT最大流二分图匹配LCA 倍增欧拉路径
动态规划编辑距离0-1 背包完全背包最长公共子序列最长递增子序列硬币找零方案数石子合并旅行商 TSP树形 DP数位 DP换根 DP
回溯与搜索N 皇后子集生成全排列组合总和迷宫寻路岛屿数量单词搜索数独A* 寻路
字符串KMP 字符串匹配Rabin-KarpBoyer-MooreManacher后缀数组LCP / height 数组AC 自动机Z 函数
数学与数论埃氏筛线性筛欧几里得算法快速幂扩展欧几里得中国剩余定理欧拉函数米勒-拉宾FFTPollard's Rho
计算几何凸包旋转卡壳最近点对线段相交扫描线求交
查找二分查找二分边界旋转数组搜索二分答案三分查找

树 Tree

数据结构 · 有层次的非线性结构(二叉搜索树)

什么是树

前面的栈、队列、数组、链表都是线性的——元素排成一条线。树不一样:它从一个根节点出发,每个节点向下长出若干子节点,像一棵倒过来的树,是非线性的层次结构。

最常用的是二叉搜索树(BST):每个节点最多两个孩子,且永远满足左子树都比它小、右子树都比它大。这条规矩让查找像猜数字一样高效——下面输入一个数试试插入或查找,看它怎么从根一路比较着往下走。

亲手试试
50
30
70
20
40
60
80

输入一个 1–99 的数,点「插入」看它走到哪、落在哪。

看见了吗——插入 35:和根 50 比,小,走左;和 30 比,大,走右;右边空了,就落在那。每下一层就排除掉一半,所以一棵平衡的 BST 查找只要 O(log n)。再点「中序遍历」——按左→根→右的顺序走一遍,吐出来的正好是升序,这是 BST 最漂亮的性质。

为什么会失衡 · 平衡的思想

BST 快,有个前提:树得长得开。可万一你按顺序插入 1 2 3 4 5 6 7——每个都比前一个大、全挂到右边,树就退化成一条链,高度变成 n,查找退回 O(n),和链表一样慢,BST 的优势全没了。

平衡树(AVL、红黑树)就是来治这个的:一发现某一支太深,就旋转几下把树重新压扁,始终保持高度 ~O(log n)。下面同样 7 个值,切换看看「退化的链」和「平衡的树」差多少。

亲手试试
1234567

高度 7 层 · 最坏查找 7 次(退回 O(n),和链表一样慢)

同样是 1–7 七个值。点「查找 7」看走几步。

退化成链,查找 7 要老老实实走 7 步;平衡的树只要 3 步。值越多差距越夸张(n vs log n)。所以真实世界的有序 map / set、数据库索引,底层用的都是自平衡的树(红黑树、B 树),保证最坏情况也快。

树在哪里用

有序查找 / 范围查询:BST、红黑树、B 树是数据库和索引的核心。
堆:用完全二叉树实现的优先队列(下一篇就讲)。
层次结构:文件系统目录、DOM、表达式解析树都是树。

树把「一条线」升级成「会分叉的层次」。下一篇讲堆——一种用数组装的完全二叉树。