php tree(九)数据结构/ 算法

数据结构 

  1. 常见数据结构与算法整理总结(上)
    • 线性表(数组,链表),栈与队列,树,二叉树,二叉查找/搜索/排序树,平衡二叉树,红黑树,图。
    • 数组和链表
      类型 分配内存方式 内存连续性 位置 查找复杂度 插入/删除
      数组 静态 连续
      • 优点:可以通过下标来访问元素
      • 缺点:若插入/删除元素,要将其后所有元素移动位置
      O(1) O(n)
      链表 动态 不连续 O(n) O(1)
    • 堆和栈队列、堆、栈、堆栈的区别?
      队列 有一个入口和一个出口,先进先出
      就像一个箱子,后进先出
      请求操作系统分配内存,效率低
  2. 数据结构中常用的树
    遍历 都是相对于根节点来说的,左节点总是在右节点前面
    • 先序:根-左-右
    • 中序:左-根-右
    • 后序:左-右-根
    表示一个节点最多能有多少个子节点,如二叉树的阶数就是2。
    指父结点下面有几个孩子结点。
    满二叉树 一棵深度为k且有2k-1(2的k次幂减1)个结点的二叉树称为满二叉树。
    完全二叉树 每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应。
    二叉树 每个结点至多只有2棵子树,二叉树的子树有左右之分,次序不能颠倒。
    • 类型:满二叉树,完全二叉树。
    1. 二叉树第 i 层上最多有2i-1个节点
    2. 深度为 k 的二叉树,最多有2k - 1个节点
    3. 对于任意一颗二叉树T,如果其终端节点数为n1度数为2的节点数为n2 则 n1 = n2 + 1
    4. 具有n个节点的完全二叉树深度为[ log2n] + 1;
    树和二叉树
    1. 二叉树每个节点最多有2个子节点,树无限制。
    2. 二叉树有序。子树分为左子树和右子树,即使某节点只有一棵子树,也要指明是左子树还是右子树。
    3. 二叉树可以是空。树不能为空,至少有一个节点。
    • BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树AVL 红黑树 B(+)树 跳表 字典树 应用场景及分析
      类型 特点 缺点 应用
      二叉查找树
      • 节点有序,利于二分查找。
      • 左子树小于它的根结点,右子树大于它的根结点,没有值相等的结点。
      • 因为不一定平衡,有可能退化成线性表,搜索性能不佳
       
      • 用于搜索
      平衡二叉树
      • 是二叉查找树
      • 严格要求平衡。左子树和右子树的深度之差的绝对值不超过1。
      • 查询性能好,维护成本高
      • 适合用于插入删除次数比较少,但查找多的情况。 
      红黑树
      • 通过任何一条从根到叶子的简单路径上各个节点的颜色进行约束,确保没有一条路径会比其他路径长2倍,因而是近似平衡的。
      • 相对于AVL树来说,旋转保持平衡次数较少。用于搜索时,插入删除次数多的情况下我们使用红黑树来取代AVL。 
      • 更新数据时,红黑树有个平衡的过程,牵涉到大量的节点,争锁的代价相对高。性能不如跳跃表。
      • epoll 在内核中的实现,用红黑树来管理事件块
      • nginx中,用红黑树来管理timer等
      • Java中的TreeMap实现
      B树/B+树
      • 多路查找树,分支多层数少,可以有效减少磁盘IO次数。
      • 相当于AVL更适合于文件系统。
      null
      • 磁盘IO是非常耗时的,为文件系统、数据库系统而生。
      跳跃表
      • 更新数据时,跳跃表需要更新的部分少,锁的东西少,性能佳
      null
      • redis sorted set
  3. 什么是B-Tree什么是B+Tree
    数据库索引
    • 索引存储在磁盘上,数据量比较大时,索引大小也跟着增长,达到几个G。
    • 利用索引进行查询时,不可能把索引全部加载到内存,只能逐一加载每个磁盘页,这里的磁盘页就对应索引树的节点。
    b树
    1. 关键字集合分布在整颗树中;
    2. 任何一个关键字出现且只出现在一个结点中;
    3. 搜索有可能在非叶子结点结束;
    4. 其搜索性能等价于在关键字全集内做一次二分查找;
    5. 自动层次控制
    b+树
    • 单节点可以存储更多的元素。使得查询磁盘IO次数更少。
    • 所有查询都要查找到叶子节点,查询性能稳定。
    • 所有叶子节点形成有序链表,便于范围查询。
  4. 数据结构之哈希表大多数分布式存储系统要么实现一个分布式Hash表,要么实现分布式B+树
  5. Redis为什么用跳表而不用平衡树?
    • 跳跃表特点
      • 在有序链表的基础上发展而来的多层链表。
      • 间隔一定元素增加指针,原链表足够长时,能跳过很多下层节点,大大加快查询速度。
      • 上层链表节点个数,是下曾节点个数一半,非常类似一个二分查找。时间复杂度O(log n)。
      • 然后对于删除和插入,采用随机生成层数,保证插入或者删除只需要修改结点前后指针,性能优于平衡树。
      • 层随机数,不超过一个最大值。
    • 对比
      类型 元素是否有序 平均复杂度/ 单key查找 范围查找 内存占用 算法实现难度 优点
      平衡树 O(log n) 复杂 复杂 平衡
      哈希表 否。所以不支持范围查询 O(1) 不支持 大(需要事先分配足够的内存存储散列表) 取决于哈希函数 查找快
      跳跃表 O(log n) 简单 灵活 简单 更新数据时,跳跃表需要更新的部分少,锁的东西少
    • sorted set数据结构实现
      • 数据较少时,由ziplist实现。
      • 数据较多时,由dict + skiplist实现。dict维护数据到分数的对应,skiplist用来根据分数范围查找数据。
      • 分数相同时,根据数据内容进行字典排序。
      • 第一层量表不是单向链表,而是一个双向链表,为了方便以倒序方式获取一个范围内元素。只有第一层链表时双向链表。

算法

  1. 常见数据结构与算法整理总结(下)
  2. 常见排序算法八大排序算法
    大类 小类 算法
    选择 选择
    • 每个数(当前数)和之后的每个数比较,每次记下小数的位置,然后交换当前数和最小数的位置
    堆排序 特点:
    • 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;
    • 或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
    构造步骤:
    • 若升序,构建大顶堆,
    • 堆顶元素和末尾元素交换,末尾表示排好的序列。
    • 对前面元素重复前2步,
    • 直到整个序列有序。
    插入 直接插入
    • 从第一个数开始,之后每个数插入前面假定排好序的位置。根据如何确定插入位置,分为直接插入(遍历)和二分查找插入
    希尔排序 改进的插入排序。按步长进行分组,每组内的元素进行插入排序。逐步减小步长,直到为1,即为普通的插入排序的情况。前面的步骤可以将所有元素变成基本是排好序的,较少要移动的元素。
    交换 冒泡
    • 每个数与下一个相邻的数比较,大的往后放。每轮下来,产生一个最大数放在最后位置(前插在后面最大数序列中)
    快速
    • 选择基准数(第一个也可以),比它大的放右边容器,小的放左边,左边和右边数做同样处理(递归),然后合并左、基准数、右边数即得
    归并排序
    • 分而治之
    基数排序 按个位大小排序、按十位大小排序、百位......
    总结 平均时间复杂度:nlogn:快速、堆、归并。关键字随机分布时,快速排序平均时间最短
  3. 查找
    顺序查找
    二分查找
    • 两个名字(二分查找、折半查找)
    • 优点三个(比较次数少、查找速度快、平均性能好)
    • 缺点两个(待查找表为有序表、插入删除困难),用数字表示就是232。8
    逐步缩小目标数组的边界。
    • 初始传入待查找数组的左右边界分别为0和数组长度-1。
    • 边界检查:如果左边界>右边界,则返回“找不到该数”,退出,
    • 将待查找数与中间位置(向下取整,只要能定出界限,无所谓多1还是少1)数比较,
    • 如果比中间位置数大,则继续在中间位置右边的数中查找(执行递归,左边界变成中间位置+1),
    • 如果比中间位置数小,则继续在中间位置左边的数中查找(执行递归,右边界变成中间位置-1),
    • 否则相等的话,表示找到待查找的数,退出。
    • 代码实现:递归与非递归实现
    分块查找 是前两者结合,分块有序,块内无序,插入和删除无需大量移动记录
    散列表
  4. 代码:常用排序和两个查找
  5. 实战:
    1. 剑指offer中的算法题数据结构和算法面试题
    2. 百钱买鸡。满足一定条件,数据在一定范围。制定for循环,剩下的事交给计算机。制定等式,接下来思路,让变量变化,所以制定for循环。
    3. 约瑟夫环。递归算法和公式法。
    4. 斐波那契数列。递归法和迭代法
    5. TopKbitmap计数,求TopK最快的方法
      常规
      1. 全局排序,再取前k个。复杂度:n*lg(n)(快速排序)。
      2. 局部排序,只对最大k个排序。使用冒泡排出k个最大数。复杂度:n*k(冒泡:n*n)。
      3. 堆排序。只找到TopK,不排序TopK。复杂度:n*lg(k)(堆排序:n*lg(n))。
      4. 分治,每个分支都要递归,例如快速排序。不懂。
      5. 减治,只要递归一个分支,例如二分查找。不懂。
      6. 随机选择+partition。不懂。
      bitmap 元素没有重复
      • 相应位的元素存在则存1,否则存0。
      • 扫描一次所有n个元素,生成bitmap,时间复杂度O(n)。
      • 生成后,去TopK只需要找到最高位的k个bit即可。
      元素有重复
      • 每个元素的一个bit变成一个计数,
      • 找TopK的过程:从高位往低位扫描,得到count之和等于k,对应的bit就是TopK所求。
    6. 全排列算法
    7. 天平称球
    8. 二进制和三进制的妙用
    9. PHP实现的算法合集

猜你喜欢

转载自www.cnblogs.com/dingqing/p/10023072.html
今日推荐