当前位置: 首页 > news >正文

Unity 3D常用的数据结构

目录

    • 数组
        • 使用场景
      • ArrayList数组
        • ArrayList的缺点
      • List\<T\>数组
        • List\<T\>有以下3点好处
    • 链表
          • 链表与数组的不同之处
          • 链表的优势
          • 数组和链表的应用场景
      • LinkedList\<T\>
        • C#中内置的双向链表LinkedList
        • 使用场景
      • 队列(Queue\<T\>)和栈(Stack\<T\>)
        • queue队列
          • 内部实现
          • 内部实现
      • Hashtable哈希表
        • 如何处理哈希冲突
          • 避免哈希冲突
          • 解决哈希冲突
            • 开放寻址法的简单实现——线性探查(Linear Probing)
            • 针对线性探查方式所存在的问题,一种改进的方式为二次探查(Quadratic Probing)
        • 二度哈希
          • 二度哈希的工作原理
          • loadFactor
          • Hashtable类的实例中添加新元素时,需要检查以保证元素与空间大小的比例不会超过最大比例。如果超过了,Hashtable类实例的空间将被扩充。空间扩充的步骤如下
      • Dictionary\<K,T\>字典
        • 冲突解决机制
        • Dictionary<K,T>类的缺点
        • 使用场景

数组

使用场景

元素的数量是固定的,并且需要使用下标时。

ArrayList数组

为了解决Array创建时必须指定长度,以及只能存放相同类型的缺点而推出的数据结构。

ArrayList的缺点
  • ArrayList是类型不安全的。因为把不同的类型都当作Object来做处理,很有可能会在使用ArrayList时发生类型不匹配的情况。
  • 数组存储值类型时并未发生装箱,但是ArrayList由于把所有类型都当作了Object,所以不可避免的是当插入值类型时会发生装箱操作,在索引取值时会发生拆箱操作。因此在频繁读写 ArrayList 时会产生额外的开销,导致性能下降。

List<T>数组

可以认为List<T> 类是 ArrayList 类的泛型等效类。

List<T>有以下3点好处
  1. 即确保了类型安全。因此List<T>是类型安全的。
  2. 取消了装箱和拆箱的操作,以及由于引入泛型而无需运行时类型检查。因此List<T>是高性能的。
  3. 融合了Array可以快速访问的优点,以及ArrayList长度可以灵活变化的优点。

链表

链表与数组的不同之处

数组中的内容在内存中是连续排列的,可以通过下标来访问。
链表中内容的顺序则是由各个对象的指针所决定的,这就决定了其内容的排列不一定是连续的,所以不能通过下标来访问。

链表的优势

使用链表最主要的优势就在于向链表中插入或删除节点时,无需考虑调整结构的容量。相反的对于数组来说容量始终是固定的,且数组中的内容在内存中是连续的。因此如果需要存放更多的数据,则面临着需要调整数组容量的现实,这就会引发新建数组、数据拷贝等一系列复杂且影响效率的操作。即使是List<T>类,虽然其对开发人员隐藏了容量调整的复杂性,但实质上性能的损耗是必须考虑的。

数组和链表的应用场景

数组适合数据的数量是有上限,且需要快速访问其元素内容的情况.
链表适合元素数量不固定且需要经常增删结点的情况。

LinkedList<T>

C#中内置的双向链表LinkedList

在Unity 3D开发过程中,由于C#已经为开发者封装了一个对应链表的类——LinkedList<T>类。因此可以很方便地通过LinkedList<T>来实现链表的功能。而和LinkedList<T>类相配套的,C#还提供了链表的结点类——LinkedListNode<T>类以用来代表链表中的结点,LinkedList<T>对象中的每个节点都属于LinkedListNode<T>类型。由于LinkedList<T>是双向链表,因此每个节点向前指向Next节点向后指向Previous节点
需要说明的一点是,LinkedList<T>类的插入和移除的运算复杂度都是O(1)。而由于该列表还维护内部计数,因此获取Count属性的运算复杂度也为 O(1)。

如何创建一个链表LinkedList<T>,以及最常见的几种操作。

  • AddFirst,将一个新结点加入该链表的第一个结点的位置;
  • RemoveFirst,将第一个结点移除;
  • AddLast,将一个新节点加入该链表最后一个结点的位置;
  • 以及在某个结点前后插入新的结点的AddBefore和AddAfter方法。
  • 对链表中的结点类LinkedListNode的各种操作。
使用场景

元素需要能够在列表的两端添加时。否则使用List<T>。

队列(Queue<T>)和栈(Stack<T>)

queue队列
内部实现

在Queue<T>内部,有一个存放类型为T的对象的环形数组,并通过head 和tail变量来指向该数组的头和尾。当使用Enqueue方法将新的元素入列时,会判断队列的长度是否足够。若不足,则依据增长因子来增加容量,例如当为初始的2.0时,则队列容量增长2倍。
在默认情况下,Queue<T>的初始化容量是32,但是也可以通过构造函数指定容量
元素的进出顺序是先进先出(FIFO)

栈(Stack)又名堆栈,它和队列一样是一种运算受限的线性表
其限制是仅允许在表的一端进行插入和删除的操作运算。这一端称为栈顶,相对的,把另一端称为栈底。
向一个栈插入新元素称为进栈、入栈或压栈。
一个栈删除元素称为出栈或退栈,它是把栈顶元素删除,使其相邻的元素成为新的栈顶元素。
元素的进出顺序是后进先出(LIFO)

内部实现

内部同样使用了数组来实现。内部结构可以通过一个垂直的数组来形象的表示。

Hashtable哈希表

哈希表(Hash Table,也叫散列表),是根据关键码/值(Key/value)而直接进行访问的数据结构。也就是说,它通过把关键码/值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫哈希函数或散列函数,存放记录的数组就叫哈希表。

如何处理哈希冲突

处理哈希冲突时,也有两种思路——避免解决

  • 冲突避免机制(Collision Avoidance)
  • 冲突解决机制(Collision Resolution)
避免哈希冲突

避免哈希冲突的一个方法就是尽可能先择合适的哈希函数。

解决哈希冲突
  1. 将要插入的元素放到另一块空间中,因为相同的哈希位置已经被占用了。
  2. 开放寻址法(Open Addressing)
开放寻址法的简单实现——线性探查(Linear Probing)
  1. 当插入新的元素时,使用哈希函数在哈希表中定位元素位置。
  2. 检查哈希表中该位置是否已经存在元素。如果该位置内容为空,则插入并返回,否则进行步骤3的操作。
  3. 如果该位置为i,则检查i+1是否为空。如果已被占用,则检查i+2。依此类推,直到找到一个内容为空的位置。

线性探查(Linear Probing)方式虽然简单,但并不是解决冲突的最好策略,因为它会导致同类哈希的聚集(Primary Clustering)。这会导致搜索哈希表时,冲突依然存在。

针对线性探查方式所存在的问题,一种改进的方式为二次探查(Quadratic Probing)

即每次检查位置空间的步长为平方倍数。也就是说,如果位置s被占用,则首先检查s+12处,然后检查s-12、s+22、s-22、s+32…以此类推,而不是像线性探查那样以s+1、s+2…方式增长。

尽管如此,二次探查同样也会导致同类哈希聚集问题(Secondary Clustering)。

二度哈希

当在哈希表中添加或获取一个元素时,会发生哈希冲突。前面简单地介绍了两种冲突解决策略,即线性探查(Linear Probing)和二次探查(Quadratic Probing)。
二度哈希使用了Θ(m2)种探查序列,而线性探查(Linear Probing)和二次探查(QuadraticProbing)使用了Θ(m)种探查序列,因此二度哈希提供了更好的避免冲突的策略。

二度哈希的工作原理

有一个包含一组哈希函数H1…Hn的集合。当需要从哈希表中添加或获取元素时,首先使用哈希函数H1。如果导致冲突,则尝试使用H2。以此类推,直到Hn。所有的哈希函数都与H1十分相似,不同的是它们选用的乘法因子(multiplicative factor)。
当使用二度哈希时,重要的是在执行了hashsize次探查后,哈希表中的每一个位置都有且只有一次被访问到。也就是说,对于给定的key,对哈希表中的同一位置不会同时使用H1和H2 。在Hashtable类中使用二度哈希公式,其始终保持(1 +((GetHash(key) >> 5) + 1) %(hashsize - 1)hashsize互为素数 (两数互为素数表示两者没有共同的质因子)

loadFactor

Hashtable类中还包含了一个私有成员变量loadFactor,loadFactor指定了哈希表中元素数量与位置(slot)数量之间的最大比例。 例如,如果loadFactor 等于0.5,则说明哈希表中只有一半的空间存放了元素值,其余一半都为空。
哈希表的构造函数允许用户指定loadFactor值,定义范围为0.1至1.0。然而不管提供的值是多少,范围都不会超过72%。即使传递的值为1.0,Hashtable类的loadFactor值还是0.72。微软官方认为loadFactor的最佳值为0.72,这平衡了速度与空间。因此,虽然默认的loadFactor为1.0,但系统内部却自动地将其改变为0.72。所以,建议使用缺省值1.0(但实际上是 0.72)。

Hashtable类的实例中添加新元素时,需要检查以保证元素与空间大小的比例不会超过最大比例。如果超过了,Hashtable类实例的空间将被扩充。空间扩充的步骤如下
  1. Hashtable类实例的位置空间几乎被翻倍。准确地说,位置空间值从当前的素数值增加到下一个最大的素数值。
  2. 因为二度哈希时,Hashtable类实例中的所有元素值将依赖于Hashtable类实例的位置空间值,所以Hashtable类实例中保存的所有值也需要重新二度哈希。

Dictionary<K,T>字典

Dictionary<K,T>使用强类型来限制Key和Item,当创建Dictionary<K,T>实例时,必须指定Key和Item的类型。

冲突解决机制

Dictionary<K,T>还采用了不同的冲突解决策略(Collision Resolution Strategy),这种技术称为链接技术(Chaining)。
链接技术(Chaining)将采用额外的数据结构来处理冲突。Dictionary<K,T>中的每个位置(slot)都映射到了一个链表。当冲突发生时,冲突的元素将被添加到桶(bucket)列表中。

Dictionary<K,T>类的缺点

它的缺点就是空间。以空间换时间,通过更多的内存开销来满足对速度的追求。在创建字典时,可以传入一个容量值,但实际使用的容量并非该值。而是使用不小于该值的最小质数作为它使用的实际容量,容量的最小值是 3。当有了实际容量后,并非直接实现索引,而是通过创建额外的两个数组来实现间接索引,即int[] buckets和Entry[] entries两个数组。因此面临的情况就是,即便新建了一个空的字典,那么伴随而来的是两个长度为3的数组。所以当处理的数据不多时,还是慎重使用字典为好,在很多情况下使用数组也是可以的

使用场景

需要使用键值对(KeyValue)来快速添加和查找,并且元素没有特定的顺序时。

相关文章:

Unity 3D常用的数据结构

目录 数组使用场景 ArrayList数组ArrayList的缺点 List\<T\>数组List\<T\>有以下3点好处 链表链表与数组的不同之处链表的优势数组和链表的应用场景 LinkedList\<T\>C#中内置的双向链表LinkedList使用场景 队列&#xff08;Queue\<T\>&#xff09;和栈…...

h5唤起微信小程序

wx-open-launch-weapp 就用这个 开放标签属于自定义标签&#xff0c;Vue会给予未知标签的警告&#xff0c;可通过配置Vue.config.ignoredElements [wx-open-launch-weapp] 来忽略Vue对开放标签的检查。 sdk授权。 调试打开时iOS会弹窗 noPermissionJsApi: []&#xff0c;confi…...

面向对象(精髓)变继承关系为组和关系(_Decorator模式)

在软件开发中&#xff0c;设计模式是解决常见问题的可重用解决方案。在面向对象编程中&#xff0c;继承和组合是两种常用的代码复用方式。然而&#xff0c;随着软件需求的不断变化&#xff0c;我们需要更灵活的设计方式来应对不断变化的需求。在本文中&#xff0c;我们将讨论从…...

MES系统在智能生产中的重要作用

在未来智能制造的发展趋势中&#xff0c;制造执行系统&#xff08;MES&#xff09;作为关键技术和工具&#xff0c;扮演着至关重要的角色。随着科技的不断进步和制造业的数字化转型&#xff0c;MES的地位将愈发凸显&#xff0c;对于企业实现智能化生产、提高效率、降低成本具有…...

2024.3.13每日一题

LeetCode 最大二进制奇数 题目链接&#xff1a;2864. 最大二进制奇数 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个 二进制 字符串 s &#xff0c;其中至少包含一个 1 。 你必须按某种方式 重新排列 字符串中的位&#xff0c;使得到的二进制数字是可以由该组…...

YOLOv5 | 涨点复现!YOLOv5添加BiFPN有效提升目标检测精度

目录 &#x1f680;&#x1f680;&#x1f680;订阅专栏&#xff0c;更新及时查看不迷路&#x1f680;&#x1f680;&#x1f680; 介绍&#xff1a; BiFPN 代码实现 ⭐欢迎大家订阅我的专栏一起学习⭐ &#x1f680;&#x1f680;&#x1f680;订阅专栏&#xff0c;更新及…...

【Nut3】nuxt.config.ts项目nuxt配置文件介绍

简言 记录下nuxt3的nuxt.config.ts文件的介绍和使用。 Nuxt Configuration nuxt.config.ts Nuxt可以通过一个单独的nuxt.config文件进行简单配置。 配置文件创建 nuxt.config文件的扩展名可以是.js、.ts或.mjs。 然后默认导出全局函数defineNuxtConfig的返回值&#xff0c…...

区块链技术的革命性影响

1. 区块链技术的基本原理&#xff1a; 区块链是一种去中心化的分布式数据库技术&#xff0c;通过不断增长的记录&#xff08;块&#xff09;构成一个链式结构。每个区块包含了交易数据的加密信息以及上一个区块的哈希值&#xff0c;从而形成了不可篡改的交易记录。这种去中心化…...

多线程(volatile)

volatile的功能 保证内存可见性禁止指令重排序 内存可见性 简单的理解 两(多)个线程同时针对一个变量进行操作, 一个线程读, 一个线程修改, 此时读到的值不一定是修改过后的值 即读线程没有感知到变量的变化 (其实是 编译器/JVM 对于代码在多线程情况下的优化进行了误判) 从 J…...

蓝桥杯 填空 卡片

蓝桥杯 填空题 卡片 解题思路&#xff1a; 我们只需要消耗完卡片的个数即可。 代码示例&#xff1a; #include<bits/stdc.h> using namespace std; int a[10]; bool isEnd(){for(int i0;i<10;i){if(a[i]-1)return false;}return true; } bool getN(int x){while(x){i…...

ELK介绍使用

文章目录 一、ELK介绍二、Elasticsearch1. ElasticSearch简介&#xff1a;2. Elasticsearch核心概念3. Elasticsearch安装4. Elasticsearch基本操作1. 字段类型介绍2. 索引3. 映射4. 文档 5. Elasticsearch 复杂查询 三、LogStash1. LogStash简介2. LogStash安装 四、kibana1. …...

【UE5】非持枪状态蹲姿移动的动画混合空间

项目资源文末百度网盘自取 在BlendSpace文件夹中单击右键选择动画(Animation)中的混合空间(Blend Space) &#xff0c;选择SK_Female_Skeleton&#xff0c;命名为BS_NormalCrouch 打开BS_NormalCrouch 水平轴表示角色的方向&#xff0c;命名为Direction&#xff0c;方向的最…...

Windows C++ TCP开发(使用select函数以及设置非阻塞/Reuse属性)

1、select官方函数说明&#xff1a; 语法 C int WSAAPI select([in] int nfds,[in, out] fd_set *readfds,[in, out] fd_set *writefds,[in, out] fd_set *exceptfds,[in] const timeval *timeout );参数 [in] nfds 已忽略。 包含 nf…...

ARM TrustZone技术解析:构建嵌入式系统的安全扩展基石

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-LOdvohfCEnd8eKyd {font-family:"trebuchet ms",verdana,arial,sans-serif;f…...

初识Python语言-课堂练习【pyhton123题库】

初识Python语言-课堂练习【pyhton123题库】 一、单项选择题 1、Guido van Rossum正式对外发布Python版本的年份是&#xff1a; A 2008B 1998C 1991D 2002 【答案】C 【解析】暂无解析2、下面不是Python语言特点的是&#xff1a;‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪…...

chrome高内存占用问题

chrome号称内存杀手不是盖的&#xff0c;不设设置的话&#xff0c;经常被它内存耗尽死机是常事。以下自用方法 1 自带的memory saver chrome://settings/performance PerformanceMemory Saver When on, Chromium frees up memory from inactive tabs. This gives active tab…...

【C语言】文件操作篇-----程序文件和数据文件,文件的打开和关闭,二进制文件和文本文件,fopen,fclose【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本篇为【C语言】文件操作篇-----程序文件和数据文件&#xff0c;文件的打开和关闭&#xff0c;二进制文件和文本文件【图文详解】&#xff0c;感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 前言 在了解完动态内存管…...

知识碎片收集

目录 1. 如何计算两点经纬度之间的距离2. 加权随机采样3.什么时LLDB和GDB 1. 如何计算两点经纬度之间的距离 1.知乎-如何计算两点经纬度间距离 2.根据两点经纬度坐标计算距离 3.根据经纬度计算两点之间的距离的公式推导过程以及google.maps的测距函数 4.根据经纬度点计算经…...

不可不知!用例图的绘制与应用全指南深度解析

在软件开发领域中&#xff0c;用例图是一种强大的工具&#xff0c;用于描述系统的功能需求以及系统与外部实体之间的交互。无论是在需求分析阶段还是在系统设计过程中&#xff0c;用例图都扮演着至关重要的角色。本文将全面介绍用例图的绘制方法和其在软件开发中的应用&#xf…...

【数据结构七】堆与PriorityQueue详解

堆 在Java中有一种数据结构基于队列&#xff0c;并保证操作的数据带有优先级&#xff0c;该数据结构应该提供了两个最基本的操作&#xff0c;一个是返回最高优先级对象&#xff0c;一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。它的底层使用了堆这种数据结…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...