数据结构与算法--非线性数据结构

目录

二叉查找树

红黑树

递归树

参考


 

树的高度,深度,层数的定义下面用图来说明这三个概念的区别
数据结构与算法--非线性数据结构

下面用图来说明这三个概念的区别

数据结构与算法--非线性数据结构

高度,这个概念跟生活中的楼层一样,从下往上数如第10层,12层起点都是地面
深度,是从上往下度量的,比如水中鱼的深度,是从水平面开始度量读
层数,跟深度类似,但计数起点是1

二叉树
满二叉树,叶子节点全都在最底层,出了叶子节点之外,每个节点都有左右两个子节点
完全二叉树,叶子节点都在最底下两层,最后一层的叶子节点都靠左排列,除了最后一层其他层的节点个数都要达到最大
数据结构与算法--非线性数据结构

完全二叉树这种特殊的定义,在用数组存储二叉树时候可以避免浪费,数组的节点都用上了没有空间浪费

数据结构与算法--非线性数据结构

二叉树的遍历
前序遍历,对于树种的任意节点,先打印这个节点,再打印它的左子树,最后打印它的右子树
中序遍历,对于树种的任意节点来说,先打印它的左子树,然后打印它本身,最后打印它的右子树
后序遍历,对于树种任意节点来说,先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身

数据结构与算法--非线性数据结构

三种遍历的代码实现

void preOrder(Node* root) {
  if (root == null) return;
  print root // 此处为伪代码,表示打印 root 节点
  preOrder(root->left);
  preOrder(root->right);
}

void inOrder(Node* root) {
  if (root == null) return;
  inOrder(root->left);
  print root // 此处为伪代码,表示打印 root 节点
  inOrder(root->right);
}

void postOrder(Node* root) {
  if (root == null) return;
  postOrder(root->left);
  postOrder(root->right);
  print root // 此处为伪代码,表示打印 root 节点
}

遍历二叉树,每个节点最多会被访问两次
所以二叉树遍历的时间复杂度是O(n)
一组数据,1,3,5,6,9,10  可以构建出多少种不同的二叉树
这是卡特兰数,是C[n,2n]/(n+1)种形式,c是组合数,节点的不同又是一种全排列
一共是n! * C[n,2n]/(n+1) 个二叉树

 

 

二叉查找树

在树种任意一个节点,其左字数中的每个节点的值,都要小于这个节点的值,而右字数节点的值都大于这个节点的值
查找,更新,插入都很容,删除比较复杂有三种情况
1.如果要删除的节点没有子节点,更新父节点指向null即可
2.要删除的节点只有一个子节点(只有左子节点或右子节点),只要更新父节点指向要删除的节点的子节点即可
3.如果有两个子节点,需要找到这个节点右子树中的最小节点,把它替换到要删除的节点上,再删除这个最小节点,也可以加个删除标记

数据结构与算法--非线性数据结构

支持重复数据的二叉查找树
插入时,如果碰到一个节点的值与要插入的值相同,就将要插入的数据放到这个节点的右子树
查找时,遇到相同节点,继续在右子树种查找,直到遇到叶子节点

数据结构与算法--非线性数据结构

删除时,先查找每个要删除的节点,再按之前的删除方式,以此删除

数据结构与算法--非线性数据结构

完全二叉树的的高度小于等于logn

有了散列表为什么还要用二叉树

  • 散列表中断数据是无序存储的,如果要输出有序数据,需要先排序,二叉树的中序遍历O(n)时间就可以输出了
  • 散列表扩容时很耗时,遇到散列冲突性能不稳定,平衡二叉树的性能非常稳定
  • 尽管散列表的查找操作时间复杂度是常量级,但因哈希冲突这个常量不一定比logn小,实际操作不一定比O(logn)块,加上函数的耗时,也不一定就比平衡二叉树效率高
  • 散列表的构造比二叉树要复杂,需要考虑散列函数的设计,冲突解决,扩容缩容,平衡二叉树只要考虑平衡这一个问题
  • 为避免过多的散列冲突,散列表的装载因子不能太大,特别是基于开放寻址法解决冲突时
     

 

红黑树

平衡二叉树

  • AVL树,查找效率高,但删除/增加维护成本高
  • 红黑树,查找/删除/增加的时间复杂度为0(logn)
  • Treap,
  • Splay Tree,这两个大部分情况下操作效率都很高,但极端情况下时间复杂度会降低

红黑树的定义

  • 根节点是黑色的
  • 每个叶子节点都是黑色的空节点(NIL),即叶子节点不存储数据
  • 任何相邻的节点都不能同时为红色,即红色节点是被黑色节点隔开的
  • 每个节点,从该节点达到其可达叶子节点的所有路径,都包含相同数目的黑色节点

增加,删除操作,可能会破坏第三,第四点
平衡调整操作,就是把第三,第四点恢复过来
红黑树的左旋和右旋操作

数据结构与算法--非线性数据结构


插入操作
红黑树规定,插入的节点必须是红色的,插入的新节点都在叶子节点上,这里有两个特殊情况

  • 如果插入节点的父节点是黑色的,那什么都不用做,它仍满足红黑树的定义
  • 如果插入节点是根节点,直接改变它的颜色,变成黑色就可以了

其他情况都会违背红黑树的定义,就需要用左旋,右旋来调整,并改变颜色
红黑树的平衡调整是一个迭代的过程,把正在处理的节点叫做 关注节点,关注节点会随着不停迭代处理,
而不断变化,最开始的关注节点就是新插入的节点
新节点插入后,如果红黑树的平衡被打破,一般会有三种情况,只需要根据每种情况的特点,不断调整,
就可以让红黑树继续符合规定,也就是继续保持平衡

CASE1,如果关注节点是a,它的叔叔节点d是红色,就执行下面操作

  • 将关注节点a的父节点b,叔叔节点d的颜色都设置成黑色
  • 将关注节点a的祖父节点c的颜色设置成红色
  • 关注节点变成a的祖父节点c
  • 跳到CASE2或者CASE3

数据结构与算法--非线性数据结构

CASE2,如果关注节点是a,它的叔叔节点d是黑色,关注节点a是其父节点b的右子节点,就执行下面操作

  • 关注节点变成a的父节点b
  • 围绕新的关注节点b左旋
  • 跳到CASE3

数据结构与算法--非线性数据结构

CASE3,如果关注节点是a,它的叔叔节点d是黑色,关注节点a是其父节点b的左子节点,就执行下面操作

  • 围绕关注节点a的祖父节点c右旋
  • 将关注节点a的父节点b,兄弟节点c颜色互换
  • 调整结束

数据结构与算法--非线性数据结构

 

 

递归树

借助递归树来分析递归算法的时间复杂度
递归的思想是,将大问题分解为小问题来求解,再将小问题分解为小小问题
把这个一层一层分解的过程画成图,就是一棵树,这棵树就是递归树
下面是归并排序的递归树,每一次是O(n),一共logn层,所以复杂度是O(n*logn)

数据结构与算法--非线性数据结构

快速排序分析
最好的情况下是区间划分后,每次都是一分为二,但这很难
假设分区后,两个分区的大小比列是1:k,当k=9时,用递推公式就是 T(n)=T(n/10)+T(9n/10)+n
用递归树表示如下
数据结构与算法--非线性数据结构

每次分区都要遍历待分区的所有数据,每一层区分操作所遍历的数据个数之和就是n,树的高度是h,复杂度是O(h*n)
快速排序的结束条件是分区大小为1,从根节点n到叶子节点1,递归树种最长路径每次要乘以9/10,最短要乘以1/10

数据结构与算法--非线性数据结构

遍历数据的个数综合就介于 nlog10n和nlog10/9 n之间,根据大O表示法,可以计算成O(n*logn)
如果k=99,或者999,这个推到仍然是成立的,从概率论角度来说,快速排序平均时间复杂度是O(n*logn)

 

斐波那契数列的时间复杂度
代码如下

if f(int n) {
    if(n==1) return 1;
    if(n==2) return 2;
    return f(n-1)+f(n-2);
}

递归树如下

数据结构与算法--非线性数据结构

f(n)分解为f(n-1)和f(n-2),每次数据规模都是-1或者-2,叶子节点的规模是1或者2
从根节点到叶子节点,每条路径长度不一样,如果每次都-1那最长路径是n,如果每次-2,那最长路径是n/2
每次分解之后合并操作只需要一次加法运算,消耗时间记做1,从上往下第一层总时间消耗是1,第二层是2,第三层是2^2
第k层是2^(k-1),整个算法的总时间消耗是每一层时间消耗之和
这个算法的时间复杂度介于O(2^n)和O(2^(n/2))之间,所以时间复杂度是指数级的

 

全排列的时间复杂度
比如把1,2,3 这三个数字做全排列,结果如下

123
132
213
231
312
321

它的递归树如下

数据结构与算法--非线性数据结构

第一层有n次交换操作,第二层是n*(n-1),第三层是n*(n-1)*(n-2)
最后一个数,n*(n-1)*(n-2)*...*2*1 等于n!
前面的n-1个数都小雨最后一个数,所以综合肯定小于n*n!
所以全排列的递归算法时间复杂度大于O(n!),小于O(n*n!),这个时间复杂度非常高

思考
1个细胞的生命周期是3小时,1小时分裂一次,求n小时候,容器内有多少细胞?

 

 

 

参考

清晰理解红黑树的演变

从2-3树到红黑树

红黑树的演示

数据结构与算法--非线性数据结构