STL的关联式容器map选择基于<Red-Black Tree红黑树>
UE4的关联式容器TMap选择基于<HashTable哈希表>
数组的特点:查询效率高,添加、删除效率低
链表的特点:查询效率低,添加、删除效率高
-->二叉树本质上是一种基于链表的数据结构,查询复杂度为
-->哈希表本质上是一种基于数组的数据结构,查询复杂度为
<1> STL和UE4采用不同实现策略的主要原因
--STL的map面向通用需求:查找和排序,增删有序
--UE4的TMap面向渲染系统:主要是查找,偶尔需要有序
<2> TMap在渲染管道中的应用
--可以看到大部分的应用情况:
---在Mesh/Material/Shader的组织和处理过程不需要TMap时刻有序
<3> Red-BlackTree红黑树
红黑树是平衡二叉树的一种,需要先来理解一下平衡二叉树的概念
完全平衡二叉树的特点
--1> 任一节点的左右两个子树的高度差的绝对值不超过1
--2> 任一节点的左右两个子树都是一棵平衡二叉树
--3> 节点的设计
AVL树
--> Adelson-Velskii & Landis在1962年的论文中发表,是一种完全平衡的二叉树
--> 实现平衡的方式
------> 左/右旋转
------> 基于左/右旋转的双旋转
------> 自顶向下的平衡
从根节点开始逐级进行平衡
红黑树
AVL树为了完全平衡需要做大量旋转,为了更好的性能,红黑树并不要求严格的平衡,通过标记树节点的颜色和限制特定颜色节点的数量进行平衡控制,左右旋转、双旋转在AVL树旋转的基础上增加了颜色控制
--1> 根节点必须为黑色
--2> 任一节点的任一路径黑节点数量相同
--3> 红节点的子节点必须为黑
--4> 平衡规则:自下而上
----不同于AVL树插入节点后从根节点开始自上而下逐级平衡,红黑树则是从插入节点位置逐级向上平衡
----GP为根节点
----GP不为根节点
可视化
-通过GeometryShader实现,分2个Pass
--<1> 显示线
--<2> 显示节点
-----TextureArray通过TexAssemble 工具生成
texassemble array -o RedArray.dds Red0.png Red1.png Red2.png Red3.png Red4.png Red5.png Red6.png
Red7.png Red8.png Red9.png Red10.png Red11.png Red12.png Red13.png Red14.png Red15.png
----TextureArray的使用
<4> HashTable哈希表
UE4基于两个Array实现TMap
---> 一个HashArray
----- 数组下标即HashIndex哈希值,存储在ElementArray中对应的ElementId
----- 哈希值的计算通过可以自定义的哈希函数,将结果对HashSize取余
---> 一个ElementArray
----- 考虑增删问题而采用SparseArray,存储Element以及相同哈希值的链表
--->如果HashIndex相同,通过HashBucket链表的方式依次指向后续Element
----UE4并没有在HashBucket链表长度大于8时转换为红黑树存储
TMap的排序Sort
-----排序Sort前
-----排序Sort
-------<1> 排序 ElementArray
-------<2> 更新 HashArray
--为什么UE4选择快速排序QuickSort
---主要的Array排序方案:
-----InsertSort插入排序 - 时间复杂度
-----BubbleSort冒泡排序 - 时间复杂度
-----QuickSort快速排序 - 时间复杂度
实测数量为64000个随机数的Array各种排序方案的性能表现