来到周末,小匹夫终于有精力和时间来更新下博客了。前段时间小匹夫读过一份代码,对其中各种数据结构灵活的使用赞不绝口,同时也大大激发了小匹夫对各种数据结构进行梳理和总结的欲望。正好最近也拜读了若干大神的文章,觉得总结下常用的数据结构以供自己也能灵活的使用变得刻不容缓。那么还是从小匹夫的工作内容入手,就谈谈在平时使用U3D时经常用到的数据结构和各种数据结构的应用场景吧。

1.几种常见的数据结构

 这里主要总结下小匹夫在工作中常碰到的几种数据结构:ArrayArrayListList<T>LinkedList<T>Queue<T>Stack<T>Dictionary<K,T>

 数组Array:

  数组是最简单的数据结构。其具有如下特点:

  1. 数组存储在连续的内存上。
  2. 数组的内容都是相同类型。
  3. 数组可以直接通过下标访问。

  数组Array的创建:

 int size = ;
int[] test = new int[size];

  创建一个新的数组时将在 CLR 托管堆中分配一块连续的内存空间,来盛放数量为size,类型为所声明类型的数组元素。如果类型为值类型,则将会有size个未装箱的该类型的值被创建。如果类型为引用类型,则将会有size个相应类型的引用被创建。

  由于是在连续内存上存储的,所以它的索引速度非常快,访问一个元素的时间是恒定的也就是说与数组的元素数量无关,而且赋值与修改元素也很简单。

string[] test2 = new string[];
//赋值
test2[] = "chen";
test2[] = "j";
test2[] = "d";
//修改
test2[] = "chenjd";

  但是有优点,那么就一定会伴随着缺点。由于是连续存储,所以在两个元素之间插入新的元素就变得不方便。而且就像上面的代码所显示的那样,声明一个新的数组时,必须指定其长度,这就会存在一个潜在的问题,那就是当我们声明的长度过长时,显然会浪费内存,当我们声明长度过短的时候,则面临这溢出的风险。这就使得写代码像是投机,小匹夫很厌恶这样的行为!针对这种缺点,下面隆重推出ArrayList。

 ArrayList:

  为了解决数组创建时必须指定长度以及只能存放相同类型的缺点而推出的数据结构。ArrayList是System.Collections命名空间下的一部分,所以若要使用则必须引入System.Collections。正如上文所说,ArrayList解决了数组的一些缺点。

  1. 不必在声明ArrayList时指定它的长度,这是由于ArrayList对象的长度是按照其中存储的数据来动态增长与缩减的。
  2. ArrayList可以存储不同类型的元素。这是由于ArrayList会把它的元素都当做Object来处理。因而,加入不同类型的元素是允许的。

  ArrayList的操作:

ArrayList test3 = new ArrayList();
//新增数据
test3.Add("chen");
test3.Add("j");
test3.Add("d");
test3.Add("is");
test3.Add();
//修改数据
test3[] = ;
//删除数据
test3.RemoveAt();

  说了那么一堆”优点“,也该说说缺点了吧。为什么要给”优点”打上引号呢?那是因为ArrayList可以存储不同类型数据的原因是由于把所有的类型都当做Object来做处理,也就是说ArrayList的元素其实都是Object类型的,辣么问题就来了。

  1. ArrayList不是类型安全的。因为把不同的类型都当做Object来做处理,很有可能会在使用ArrayList时发生类型不匹配的情况。
  2. 如上文所诉,数组存储值类型时并未发生装箱,但是ArrayList由于把所有类型都当做了Object,所以不可避免的当插入值类型时会发生装箱操作,在索引取值时会发生拆箱操作。这能忍吗?

注:为何说频繁的没有必要的装箱和拆箱不能忍呢?且听小匹夫慢慢道来:所谓装箱 (boxing):就是值类型实例到对象的转换(百度百科)。那么拆箱:就是将引用类型转换为值类型咯(还是来自百度百科)。下面举个栗子~

//装箱,将String类型的值FanyoyChenjd赋值给对象。
int info = 1989;
object obj=(object)info; //拆箱,从Obj中提取值给info
object obj = 1;
int info = (int)obj;

那么结论呢?好吧,请允许小匹夫很low再次引用百度百科。显然,从原理上可以看出,装箱时,生成的是全新的引用对象,这会有时间损耗,也就是造成效率降低。

 List<T>泛型List

  为了解决ArrayList不安全类型与装箱拆箱的缺点,所以出现了泛型的概念,作为一种新的数组类型引入。也是工作中经常用到的数组类型。和ArrayList很相似,长度都可以灵活的改变,最大的不同在于在声明List集合时,我们同时需要为其声明List集合内数据的对象类型,这点又和Array很相似,其实List<T>内部使用了Array来实现。

List<string> test4 = new List<string>();  

//新增数据
test4.Add(“Fanyoy”);
test4.Add(“Chenjd”); //修改数据
test4[] = “murongxiaopifu”; //移除数据
test4.RemoveAt();

  这么做最大的好处就是

  1. 即确保了类型安全。
  2. 也取消了装箱和拆箱的操作。
  3. 它融合了Array可以快速访问的优点以及ArrayList长度可以灵活变化的优点。

  LinkedList<T>

  也就是链表了。和上述的数组最大的不同之处就是在于链表在内存存储的排序上可能是不连续的。这是由于链表是通过上一个元素指向下一个元素来排列的,所以可能不能通过下标来访问。如图

  既然链表最大的特点就是存储在内存的空间不一定连续,那么链表相对于数组最大优势和劣势就显而易见了。

  1. 向链表中插入或删除节点无需调整结构的容量。因为本身不是连续存储而是靠各对象的指针所决定,所以添加元素和删除元素都要比数组要有优势。
  2. 链表适合在需要有序的排序的情境下增加新的元素,这里还拿数组做对比,例如要在数组中间某个位置增加新的元素,则可能需要移动移动很多元素,而对于链表而言可能只是若干元素的指向发生变化而已。
  3. 有优点就有缺点,由于其在内存空间中不一定是连续排列,所以访问时候无法利用下标,而是必须从头结点开始,逐次遍历下一个节点直到寻找到目标。所以当需要快速访问对象时,数组无疑更有优势。

  综上,链表适合元素数量不固定,需要经常增减节点的情况。

  关于链表的使用,MSDN上有详细的例子

  Queue<T>

  在Queue<T>这种数据结构中,最先插入在元素将是最先被删除;反之最后插入的元素将最后被删除,因此队列又称为“先进先出”(FIFO—first in first out)的线性表。通过使用Enqueue和Dequeue这两个方法来实现对 Queue<T> 的存取。

  一些需要注意的地方:

  1. 先进先出的情景。
  2. 默认情况下,Queue<T>的初始容量为32, 增长因子为2.0。
  3. 当使用Enqueue时,会判断队列的长度是否足够,若不足,则依据增长因子来增加容量,例如当为初始的2.0时,则队列容量增长2倍。
  4. 乏善可陈。

  关于Queue<T>的使用方法,MSDN上也有相应的例子

  Stack<T>

  

  与Queue<T>相对,当需要使用后进先出顺序(LIFO)的数据结构时,我们就需要用到Stack<T>了。

  一些需要注意的地方:

  1. 后进先出的情景。
  2. 默认容量为10。
  3. 使用pop和push来操作。
  4. 乏善可陈。

  同样,在这里你也可以看到大量Stack<T>的例子。

  Dictionary<K,T>

  字典这东西,小匹夫可是喜欢的不得了。看官们自己也可以想想字典是不是很招人喜欢,创建一个字典之后就可以往里面扔东西,增加、删除、访问那叫一个快字了得。但是直到小匹夫日前看了一个大神的文章,才又想起了那句话“啥好事咋能让你都占了呢”。那么字典背后到底隐藏着什么迷雾,拨开重重迷雾之后,是否才是真相?且听下回分。。。等等,应该是下面就让我们来分析一下字典吧。

  提到字典就不得不说Hashtable哈希表以及Hashing(哈希,也有叫散列的),因为字典的实现方式就是哈希表的实现方式,只不过字典是类型安全的,也就是说当创建字典时,必须声明key和item的类型,这是第一条字典与哈希表的区别。关于哈希表的内容推荐看下这篇博客哈希表。关于哈希,简单的说就是一种将任意长度的消息压缩到某一固定长度,比如某学校的学生学号范围从00000~99999,总共5位数字,若每个数字都对应一个索引的话,那么就是100000个索引,但是如果我们使用后3位作为索引,那么索引的范围就变成了000~999了,当然会冲突的情况,这种情况就是哈希冲突(Hash Collisions)了。扯远了,关于具体的实现原理还是去看小匹夫推荐的那篇博客吧,当然那篇博客上面那个大大的转字也是蛮刺眼的。。。

  回到Dictionary<K,T>,我们在对字典的操作中各种时间上的优势都享受到了,那么它的劣势到底在哪呢?对嘞,就是空间。以空间换时间,通过更多的内存开销来满足我们对速度的追求。在创建字典时,我们可以传入一个容量值,但实际使用的容量并非该值。而是使用“不小于该值的最小质数来作为它使用的实际容量,最小是3。”(老赵),当有了实际容量之后,并非直接实现索引,而是通过创建额外的2个数组来实现间接的索引,即int[] buckets和Entry[] entries两个数组(即buckets中保存的其实是entries数组的下标),这里就是第二条字典与哈希表的区别,还记得哈希冲突吗?对,第二个区别就是处理哈希冲突的策略是不同的!字典会采用额外的数据结构来处理哈希冲突,这就是刚才提到的数组之一buckets桶了,buckets的长度就是字典的真实长度,因为buckets就是字典每个位置的映射,然后buckets中的每个元素都是一个链表,用来存储相同哈希的元素,然后再分配存储空间。

因此,我们面临的情况就是,即便我们新建了一个空的字典,那么伴随而来的是2个长度为3的数组。所以当处理的数据不多时,还是慎重使用字典为好,很多情况下使用数组也是可以接受的。

2.几种常见数据结构的使用情景

Array

需要处理的元素数量确定并且需要使用下标时可以考虑,不过建议使用List<T>

ArrayList

不推荐使用,建议用List<T>

List<T>泛型List

需要处理的元素数量不确定时 通常建议使用

LinkedList<T>

链表适合元素数量不固定,需要经常增减节点的情况,2端都可以增减

Queue<T>

先进先出的情况

Stack<T>

后进先出的情况

Dictionary<K,T>

需要键值对,快速操作

  

  

  

装模作样的声明一下:本博文章若非特殊注明皆为原创,若需转载请保留原文链接及作者信息慕容小匹夫

Unity3D中常用的数据结构总结与分析的更多相关文章

  1. (转)Unity3D中常用的数据结构总结与分析

    http://www.cnblogs.com/murongxiaopifu/p/4161648.html#array   1.几种常见的数据结构 常碰到的几种数据结构:Array,ArrayList, ...

  2. Unity3D中常用的数据结构总结与分

    阅读目录 1.几种常见的数据结构 2.几种常见数据结构的使用情景 来到周末,小匹夫终于有精力和时间来更新下博客了.前段时间小匹夫读过一份代码,对其中各种数据结构灵活的使用赞不绝口,同时也大大激发了小匹 ...

  3. Unity3D中常用的数据结构 学习

    Array 1.数组存储在连续的内存上. 2.数组的元素都是相同类型或者类型的衍生类型 3.数组可以直接通过下标访问 ArrayList 1.不必在声明ArrayList时指定它的长度,这是由于Arr ...

  4. java中常用的数据结构--Collection接口及其子类

    java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类. 一.集合和数组的区别 二.C ...

  5. 【Unity3d游戏开发】Unity3D中常用的物理学公式

    马三最近在一直负责Unity中的物理引擎这一块,众所周知,Unity内置了NVIDIA公司PhysX物理引擎.然而,马三一直觉得只会使用引擎而不去了解原理的程序猿不是一位老司机.所以对一些常用的物理学 ...

  6. Linux内核中常用的数据结构和算法(转)

    知乎链接:https://zhuanlan.zhihu.com/p/58087261 Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树. 链表 Linux内核代码大量使用了 ...

  7. Java中常用的数据结构类

    结构体系图 List ArrayList.LinkedList.Vector有什么区别? ArrayList 只能装入引用对象(基本类型要转换为封装类): 线程不安全: 底层由数组实现(顺序表),因为 ...

  8. 关于Unity中常用的数据结构和JSON处理(专题三)

    数据结构通俗来讲就是用某个对象去存储数据集合,比如要存储100个整数,要用什么样的数据类型能把它们存储好. Jason处理,服务器对接,配置文件的使用,Unity和Jason之间相互的转换. Arra ...

  9. Unity中常用的数据结构总结

    本篇博文对U3D经常用到的数据结构和各种数据结构的应用场景总结下. 1.几种常见的数据结构 这里主要总结下在工作中常碰到的几种数据结构:Array,ArrayList,List<T>,Li ...

随机推荐

  1. 结巴分词3--基于汉字成词能力的HMM模型识别未登录词

    作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 1 算法简介 在 结巴分词2--基于前缀词典及动态规划实现分词 博 ...

  2. 简约之美Jodd-http--深入源码理解http协议

    Jodd 是一个开源的 Java 工具集, 包含一些实用的工具类和小型框架.简单,却很强大! jodd-http是一个轻巧的HTTP客户端.现在我们以一个简单的示例从源码层看看是如何实现的? Http ...

  3. jQuery可自动播放动画焦点图插件Koala

    Koala是一款简单而实用的jQuery焦点图幻灯片插件,焦点图不仅可以在播放图片的时候让图片有淡入淡出的动画效果,而且图片可以自动播放.该jQuery焦点图的每一张图片都可以设置文字描述,并浮动在图 ...

  4. iOS10之Expected App Behaviors

    昨天上架到appStore的时候碰到个问题,构建好后上传到itunesconnect的的包都用不了, 显示错误为:此构建版本无效. 或者英文显示为:ITC.apps.preReleaseBuild.e ...

  5. Java 进阶 hello world! - 中级程序员之路

    Java 进阶 hello world! - 中级程序员之路 Java是一种跨平台的语言,号称:"一次编写,到处运行",在世界编程语言排行榜中稳居第二名(TIOBE index). ...

  6. SQLite学习笔记(十)&&加密

    随着移动互联网的发展,手机使用越来越广泛,sqlite作为手机端存储的一种解决方案,使用也非常普遍.但是sqlite本身安全特性却比较弱,比如不支持用户权限,只要能获取到数据库文件就能进行访问:另外也 ...

  7. C 盘的不速之客

      C 盘的报告内容既然上GB的空间 操作系统版本 原来是微软这个查找解决异常关闭解决方案生成的报告   参考 How To Disable Vista Error Reporting Feature ...

  8. Visual Studio Code 配置指南

    Visual Studio Code (简称 VS Code)是由微软研发的一款免费.开源的跨平台文本(代码)编辑器.在我看来它是「一款完美的编辑器」. 本文是有关 VS Code 的特性介绍与配置指 ...

  9. Git 进阶指南(git ssh keys / reset / rebase / alias / tag / submodule )

    在掌握了基础的 Git 使用 之后,可能会遇到一些常见的问题.以下是猫哥筛选总结的部分常见问题,分享给各位朋友,掌握了这些问题的中的要点之后,git 进阶也就完成了,它包含以下部分: 如何修改 ori ...

  10. Storm介绍(二)

    作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文是Storm系列之一,主要介绍Storm的架构设计,推荐读者在阅读 ...