二分查找
定义
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列
.时间复杂度 O(logn)
实现思路
递归 - 代码逻辑更加简洁
const binarySearch = (arr,target,startIndex,endIndex) => {
const length = arr.length;
if(length === 0 ) return -1;
// 开始和结束的范围
if(startIndex == null) startIndex = 0;
if(endIndex == null) endIndex = length -1;
// 如果 start 和 end 相遇,则结束
if(startIndex > endIndex) return - 1;
// 中间位置
const midIndex = Math.floor((startIndex + endIndex) / 2);
const midValue = arr[midIndex];
if(target < midValue){
// 目标值较小,则继续在左侧查找
return binarySearh(arr, target, startIndex,midIndex - 1)
}else if(target > midValue){
// 目标值较大,则继续在右侧查找
return binarySearh(arr, target, midIndex + 1,endIndex)
}else{
// 相等,返回
return midIndex
}
}
// // // 功能测试
// const arr = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]
// const target = 40
// // console.info(binarySearch2(arr, target))
循环 - 性能更好
(就调用一次函数,而递归需要调用很多次函数,创建函数作用域会消耗时间)
const binarySearch = (arr,targetr)=>{
const length = arr.length;
if(length === 0) retrun -1;
let startIndex = 0;
let endIndex = length -1;
while(starIndex <=endIndex){
const midIndex = Math.floor((startIndex+endIndex)/2);
const midValue = arr[midIndex];
if(target<midValue){
endIndex = midIndex -1
}else if(target>midValue){
startIndex = midIndex +1
}else{
return midIndex
}
}
return -1
}
二叉树
定义
树是常见的数据结构,如 DOM 树,是一种多叉树。二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。
为什么重要?
- 二叉树,可以充分利用
二分法
- 二叉树可以同时规避数字和链表的缺点
二叉树的遍历
- 前序遍历:root -> left -> right
- 中序遍历:left -> root -> right
- 后序遍历:left -> right -> root
interface ITreeNode {
value: number
left: ITreeNode | null
right: ITreeNode | null
}
const arr: number[] = []
const preOrderTraverse = (node:ITreeNode | null):void =>{
if(node === null) return;
arr.push(node.value);
preOrderTraverse(node.left);
preOrderTraverse(node.right);
}
二叉搜索树 BST
有序结构
- 数组:查找易,增删难
- 链表:增删易,查找难
将两者优点结合起来 —— 二叉搜索树 BST :查找易,增删易 —— 可使用二分算法
特性
1.左子树上所有结点的值均小于或等于它的根结点的值。
2.右子树上所有结点的值均大于或等于它的根结点的值。
3.左、右子树也分别为二叉排序树。
寻找 BST 里的第 K 小值
根据 BST 的特点,中序遍历
的结果,正好是按照从小到大排序的结果。
所以,中序遍历,求数组的 arr[k]
即可。
BBST (Balance Binary Search Tree) 平衡二叉搜索树
二叉搜索树 BST ,如果左右不平衡,也无法做到最优
极端情况下,它就成了链表
适度平衡的BST
称为BBST
- 树高度
h
约等于logn
- 查找、增删,时间复杂度都等于
O(logn)
红黑树
一种自动平衡的二叉树
- 节点分 红/黑 两种颜色,通过颜色转换来维持树的平衡
- 相比于普通平衡二叉树,它维持平衡的效率更高
红黑树的特性(规则)如下:
1.结点是红色或黑色。
2.根结点是黑色。
3.每个叶子结点都是黑色的空结点(NIL结点)。
4.每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)
5.从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。
AVL (Adelson-Velsky-Landis Tree) 自适应平衡二叉搜索树
在AVL树当中,我们通过“平衡因子”来判断一颗二叉树是否符合高度平衡。
到底什么是AVL树的平衡因子
呢?
对于AVL树的每一个结点,平衡因子是它的左子树高度和右子树高度的差值。只有当二叉树所有结点的平衡因子都是-1, 0, 1这三个值的时候,这颗二叉树才是一颗合格的AVL树
。
举个例子,下图就是一颗典型的AVL树,每个节点旁边都标注了平衡因子:
其中结点4的左子树高度是1,右子树不存在,所以该结点的平衡因子是1-0=1。
结点7的左子树不存在,右子树高度是1,所以平衡因子是0-1=-1。
所有的叶子结点,不存在左右子树,所以平衡因子都是0。
B 树
物理上是多叉树,但逻辑上是一个 BST 。用于高效 I/O ,如关系型数据库就用 B 树来组织数据结构。
哈夫曼树
夫曼树(Huffman Tree)是在叶子结点和权重确定的情况下,带权路径长度最小的二叉树,也被称为最优二叉树。
mp.weixin.qq.com/s/dX-8zmSem… mp.weixin.qq.com/s/3uCQj0-WB…
堆
- 完全二叉树
- 最大堆:父节点>=子节点
- 最小堆:父节点<=子节点
堆,虽然逻辑上是二叉树
,但实际上它使用数组来存储的
。
堆对比BST
- 查询比 BST 慢
- 增删比 BST 快,维持平衡也更快
- 但整体复杂度都是
O(logn)
级别,即树的高度
但结合堆的应用场景
- 一般使用内存地址(栈中保存了)来查询,不会直接从根节点搜索
- 堆的物理结构是数组,所以查询复杂度就是
O(1)
总结
- 物理结构是数组(空间更小),逻辑结构是二叉树(操作更快)
- 适用于“堆栈”结构