位置: 编程技术 - 正文
推荐整理分享UnityCode常用数据结构大起底(unity常用代码),希望有所帮助,仅作参考,欢迎阅读内容。
文章相关热门搜索词:unity常用数据结构和算法,unity数据类型,unity代码大全,unity数据类型,unity 数据,unity 数据,unity常用代码,unity code,内容如对您有帮助,希望把文章链接给更多的朋友!
1.几种常见的数据结构 这里主要总结下小匹夫在工作中常碰到的几种数据结构:Array,ArrayList,List<T>,LinkedList<T>,Queue<T>,Stack<T>,Dictionary<K,T>数组Array: 数组是最简单的数据结构。其具有如下特点:
数组存储在连续的内存上。
数组的内容都是相同类型。
数组可以直接通过下标访问。
数组Array的创建:
int size = 5;
int[] test = new int[size];
创建一个新的数组时将在 CLR 托管堆中分配一块连续的内存空间,来盛放数量为size,类型为所声明类型的数组元素。如果类型为类型,则将会有size个未装箱的该类型的被创建。如果类型为引用类型,则将会有size个相应类型的引用被创建。 由于是在连续内存上存储的,所以它的索引速度非常快,访问一个元素的时间是恒定的也就是说与数组的元素数量无关,而且赋与修改元素也很简单。
string[] test2 = new string[3];
//赋
test2[0] = "chen";
test2[1] = "j";
test2[2] = "d";
//修改
test2[0] = "chenjd";
但是有优点,那么就一定会伴随着缺点。由于是连续存储,所以在两个元素之间插入新的元素就变得不方便。而且就像上面的代码所显示的那样,声明一个新的数组时,必须指定其长度,这就会存在一个潜在的问题,那就是当我们声明的长度过长时,显然会浪费内存,当我们声明长度过短的时候,则面临这溢出的风险。这就使得写代码像是投机,小匹夫很厌恶这样的行为!针对这种缺点,下面隆重推出ArrayList。ArrayList: 为了解决数组创建时必须指定长度以及只能存放相同类型的缺点而推出的数据结构。ArrayList是System.Collections命名空间下的一 部分,所以若要使用则必须引入System.Collections。正如上文所说,ArrayList解决了数组的一些缺点。
不必在声明ArrayList时指定它的长度,这是由于ArrayList对象的长度是按照其中存储的数据来动态增长与缩减的。
ArrayList可以存储不同类型的元素。这是由于ArrayList会把它的元素都当做Object来处理。因而,加入不同类型的元素是允许的。
ArrayList的操作:
ArrayList test3 = new ArrayList();
//新增数据
test3.Add("chen");
test3.Add("j");
test3.Add("d");
test3.Add("is");
test3.Add();
//修改数据
test3[4] = ;
//删除数据
test3.RemoveAt(4);
说了那么一堆”优点“,也该说说缺点了吧。为什么要给”优点”打上引号呢?那是因为ArrayList可以存储不同类型数据的原因是由于把所有的类型都当做Object来做处理,也就是说ArrayList的元素其实都是Object类型的,辣么问题就来了。
ArrayList不是类型安全的。因为把不同的类型都当做Object来做处理,很有可能会在使用ArrayList时发生类型不匹配的情况。
如上文所诉,数组存储类型时并未发生装箱,但是ArrayList由于把所有类型都当做了Object,所以不可避免的当插入类型时会发生装箱操作,在索引取时会发生拆箱操作。这能忍吗?
注:为何说频繁的没有必要的装箱和拆箱不能忍呢?且听小匹夫慢慢道来:所谓装箱 (boxing):就是类型实例到对象的转换(百度百科)。那么拆箱:就是将引用类型转换为类型咯(还是来自百度百科)。下面举个栗子~
//装箱,将String类型的FanyoyChenjd赋给对象。
String info = ”FanyoyChenjd”;
object obj=(object)info;
//拆箱,从Obj中提取给info
object obj = "FanyoyChenjd";
String info = (String)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[1] = “murongxiaopifu”;
//移除数据
test4.RemoveAt(0);
这么做最大的好处就是
即确保了类型安全。
也取消了装箱和拆箱的操作。
它融合了Array可以快速访问的优点以及ArrayList长度可以灵活变化的优点。
假设各位和小匹夫一样,在工作中最常使用的一种数据结构就是它。那么我们是否能再多一点好奇心呢?那就是探究一下,如果我们自己实现一个类的数据结构,该从何处下手呢?下面小匹夫就抛砖引玉了。刚才说过了,List<T>的内部其实也是一个Array,且是强类型的,所以我们的简单实现(暂且称之为 EggArray<T>)也秉承这个特点,内部通过一个Array来实现,且需要声明类型。但是同时我们也看到List<T>继 承和实现了很多接口,比如IEnumerable接口等,而且类型和引用类型通吃。这里为了EggArray<T>实现起来轻装简行,我们 不继承List<T>继承的各种接口,同时我们的EggArray只服务于引用类型。那么首先明确了,它是一个处理引用类型,且实现了泛型的。那么定义就出来了:
//EggArray类
//定义
public class EggArray<T> where T : class
{
}
那么下一步呢?该确定它的内部成员了,就先从字段和属性开始吧。属性&变量
//EggArray<T>的属性&&变量
private int capacity;
private int count;
private T[] items;
public int Count
{
get
{
return this.count;
}
}
public int Capacity
{
get
{
return this.capacity;
}
}
之后呢?好像是需要一个构造函数了。上文也说了,貌new的时候不需要指定容量呀。那么我们就把构造函数做成这样吧。构造函数:
//EggArray的构造函数,默认容量为8
public EggArray() : this(8)
{
}
public EggArray(int capacity)
{
this.capacity = capacity;
this.items = new T[capacity];
}
好了,构造函数也说完了,那么就介绍一下私有方法,因为运行机制全部是有私有方法来运筹的,公共方法只不过是开放给我们的使用的罢了。小匹夫对公共方法的实现没有兴趣,这里就不做演示了。刚刚也说了,List<T>是无所谓初始长度的,可以用Add()方法往里面添加元素,同时也不可能是有一个无限大的空间让它来存储,那么究 竟它究竟为何能做到这一点呢?因为有一个能动态调整内部数组大小的方法存在,且调整大小是按照原有长度成倍增长的。我们姑且称之为Resize。那么在进行下面的内容之前,小匹夫还想先问各位一个问题:
List<int> test = new List<int>(){0,1,2,3,4,5,6,7,8,9};
int count = 0;
for(int i = 0; i < test.Count; i)
{
if(i == 1)
test.Remove(test[i]);
count;
}
Debug.Log (count);
上面这段代码会输出什么呢?答案是9。可能有的盆油会感到奇怪,test进去时长度明明是啊。就算你中间Remove了一个元素,可为什么会影响后面 的元素呢?(比如把index为1的元素remove掉,原来index为2的元素现在的index就成1了。)感觉乱套有木有?其实这里 List<T>在执行remove的同时,也把内部的数组压缩了。所以也肯定有一个方法用来压缩咯。我们姑且称为Compact。私有方法
//当数组元素个[/size][/backcolor][/color][i][color=White][backcolor=DarkGreen][size=2]数不小于数组容量时,需要扩容,增长因子growthFactor为2
private void Resize()
{
int capacity = this.capacity * growthFactor;
if (this.count > capacity)
{
this.count = capacity;
}
T[] destinationArray = new T[capacity];
Array.Copy(this.items, destinationArray, this.count);
this.items = destinationArray;
this.capacity = capacity;
}
private void Compact()
{
int num = 0;
for (int i = 0; i < this.count; i)
{
if (this.items[i] == null)
{
num;
}
else if (num > 0)
{
this.items[i - num] = this.items[i];
this.items[i] = null;
}
}
this.count -= num;
}[i][i][i]
LinkedList<T> 也就是链表了。和上述的数组最大的不同之处就是在于链表在内存存储的排序上可能是不连续的。这是由于链表是通过上一个元素指向下一个元素来排列的,所以可能不能通过下标来访问。如图 既然链表最大的特点就是存储在内存的空间不一定连续,那么链表相对于数组最大优势和劣势就显而易见了。
向链表中插入或删除节点无需调整结构的容量。因为本身不是连续存储而是靠各对象的指针所决定,所以添加元素和删除元素都要比数组要有优势。
链表适合在需要有序的排序的情境下增加新的元素,这里还拿数组做对比,例如要在数组中间某个位置增加新的元素,则可能需要移动移动很多元素,而对于链表而言可能只是若干元素的指向发生变化而已。
有优点就有缺点,由于其在内存空间中不一定是连续排列,所以访问时候无法利用下标,而是必须从头结点开始,逐次遍历下一个节点直到寻找到目标。所以当需要快速访问对象时,数组无疑更有优势。
综上,链表适合元素数量不固定,需要两端存取且经常增减节点的情况。 关于链表的使用,MSDN上有详细的例子。Queue<T> 在Queue<T>这种数据结构中,最先插入在元素将是最先被删除;反之最后插入的元素将最后被删除,因此队列又称为“先进先出”(FIFO —first in first out)的线性表。通过使用Enqueue和Dequeue这两个方法来实现对 Queue<T> 的存取。 一些需要注意的地方:
先进先出的情景。
默认情况下,Queue<T>的初始容量为, 增长因子为2.0。
当使用Enqueue时,会判断队列的长度是否足够,若不足,则依据增长因子来增加容量,例如当为初始的2.0时,则队列容量增长2倍。
乏善可陈。
关于Queue<T>的使用方法,MSDN上也有相应的例子。Stack<T> 与Queue<T>相对,当需要使用后进先出顺序(LIFO)的数据结构时,我们就需要用到Stack<T>了。 一些需要注意的地方:
后进先出的情景。
默认容量为。
使用pop和push来操作。
乏善可陈。
同样,在MSDN你也可以看到大量Stack<T>的例子。Dictionary<K,T> 字典这东西,小匹夫可是喜欢的不得了。看官们自己也可以想想字典是不是很招人喜欢,创建一个字典之后就可以往里面扔东西,增加、删除、访问那叫一个快字了 得。但是直到小匹夫日前看了一个大神的文章,才又想起了那句话“啥好事咋能让你都占了呢”。那么字典背后到底隐藏着什么迷雾,拨开重重迷雾之后,是否才是 真相?且听下回分。。。等等,应该是下面就让我们来分析一下字典吧。 提到字典就不得不说Hashtable哈希表以及Hashing(哈希,也有叫散列的),因为字典的实现方式就是哈希表的实现方式,只不过字典是类型安全的,也就是说当创建字典时,必须声明key和item的类型,这是第一条字典与哈希表的区别。关于哈希表的内容推荐看下这篇博客哈希表。关于哈希, 简单的说就是一种将任意长度的消息压缩到某一固定长度,比如某学校的学生学号范围从~,总共5位数字,若每个数字都对应一个索引的 话,那么就是个索引,但是如果我们使用后3位作为索引,那么索引的范围就变成了~了,当然会冲突的情况,这种情况就是哈希冲突(Hash Collisions)了。扯远了,关于具体的实现原理还是去看小匹夫推荐的那篇博客吧,当然那篇博客上面那个大大的转字也是蛮刺的。。。 回到Dictionary<K,T>,我们在对字典的操作中各种时间上的优势都享受到了,那么它的劣势到底在哪呢?对嘞,就是空间。以空 间换时间,通过更多的内存开销来满足我们对速度的追求。在创建字典时,我们可以传入一个容量,但实际使用的容量并非该。而是使用“不小于该的最小质数来作为它使用的实际容量,最小是3。”(老赵),当有了实际容量之后,并非直接实现索引,而是通过创建额外的2个数组来实现间接的索引,即int[] buckets和Entry[] entries两个数组(即buckets中保存的其实是entries数组的下标),这里就是第二条字典与哈希表的区别,还记得哈希冲突吗?对,第二个区别就是处理哈希冲突的策略是不同的!字典会采用额外的数据结构来处理哈希冲突,这就是刚才提到的数组之一buckets桶了,buckets的长度就是字典的真实长度,因为buckets就是字典每个位置的映射,然后buckets中的每个元素都是一个链表,用来存储相同哈希的元素,然后再分配存储空间。因此,我们面临的情况就是,即便我们新建了一个空的字典,那么伴随而来的是2个长度为3的数组。所以当处理的数据不多时,还是慎重使用字典为好,很多情况下使用数组也是可以接受的。2.几种常见数据结构的使用情景
C#常用集合的使用分类: C# -- : 人阅读 评论(0)收藏举报大多数集合都在System.Collections,System.Collections.Generic两个命名空间。其中System.Collections.Generic专门用于泛型集合。
针对特定类型的集合类型位于System.Collections.Specialized;命名空间;
线程安全的集合类位于System.Collections.Concurrent;命名空间。
下面是集合和列表实现的接口如下:
一、列表
[csharp] view plaincopyprint?[Serializable] [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))] [DebuggerDisplay("Count = {Count}")] public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable从这个可以看出,泛型集合List<T>实现了这么多接口,具体接口的信息可以通过工具查看。
[csharp] view plaincopyprint?using System; using System.Collections.Generic; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { List<String> list = new List<string>(); list.Add("张三"); list.Add("李四"); list.Add("王五"); list.Add("田六"); list.Add("赵七"); for (int i = 0; i < list.Count; i) { Console.WriteLine("for循环:" i.ToString() "=" list[i]); } list.RemoveAt(0); foreach (String item in list) { Console.WriteLine("foreach迭代:" item); } list.AddRange(new String[] { "Hello1", "Hello2", "Hello3" }); list.ForEach(Print); Console.Read(); } private static void Print(String item) { Console.WriteLine("ForEach:" item); } } }二、队列
队列先进先出,一头进一头出,用Queue<T>实现
[csharp] view plaincopyprint?[Serializable] [DebuggerTypeProxy(typeof(System_QueueDebugView<>))] [ComVisible(false)] [DebuggerDisplay("Count = {Count}")] public class Queue<T> : IEnumerable<T>, ICollection, IEnumerable可以看出队列实现了集合的接口,迭代的接口
[csharp] view plaincopyprint?using System; using System.Collections.Generic; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { Queue<String> queue = new Queue<string>(); //进队 queue.Enqueue("张三"); queue.Enqueue("李四"); queue.Enqueue("王五"); queue.Enqueue("田六"); queue.Enqueue("赵七"); foreach (String item in queue) { Console.WriteLine("foreach迭代:" item); } //出队 while (queue.Count > 0) { Console.WriteLine("出队:" queue.Dequeue()); } Console.Read(); } } }三、栈
栈:从同一边先进后出,用Stack<T>实现
[csharp] view plaincopyprint?[DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(System_StackDebugView<>))] [ComVisible(false)] public class Stack<T> : IEnumerable<T>, ICollection, IEnumerable栈也是实现了集合接口与迭代接口的
[csharp] view plaincopyprint?using System; using System.Collections.Generic; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { Stack<String> stack = new Stack<string>(); //进栈 stack.Push("张三"); stack.Push("李四"); stack.Push("王五"); stack.Push("田六"); stack.Push("赵七"); foreach (String item in stack) { Console.WriteLine("foreach迭代:" item); } //出栈 while (stack.Count > 0) { Console.WriteLine("出栈:" stack.Pop()); } Console.Read(); } } }四、链表
LinkedList是一个双向链表,链表有个有点,就是在链表中间插入、删除元素很快,但是查找中间与末尾的元素很慢,需要一个节点一个节点的去找。
[csharp] view plaincopyprint?[Serializable] [DebuggerTypeProxy(typeof(System_CollectionDebugView<>))] [DebuggerDisplay("Count = {Count}")] [ComVisible(false)] public class LinkedList<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable, ISerializable, IDeserializationCallback由此可见链表也是有集合的特性的,可以迭代,同时还有链表的特性
[csharp] view plaincopyprint?using System; using System.Collections.Generic; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { LinkedList<String> lList = new LinkedList<string>(); LinkedListNode<String> node = new LinkedListNode<string>("root"); lList.AddFirst(node); node = lList.AddAfter(node, "张三"); node = lList.AddAfter(node, "李四"); node = lList.AddAfter(node, "王五"); node = lList.AddAfter(node, "田六"); node = lList.AddAfter(node, "赵七"); foreach (String item in lList) { Console.WriteLine("foreach迭代:" item); } node = lList.First; Console.WriteLine("第一个元素:" node.Value); node = lList.Last; Console.WriteLine("最后一个元素:" node.Value); Console.Read(); } } }五、有序列表
SortedList采用键-对存储,键不能重复,并且会根据key进行排序
[csharp] view plaincopyprint?[Serializable] [DebuggerTypeProxy(typeof(System_DictionaryDebugView<,>))] [DebuggerDisplay("Count = {Count}")] [ComVisible(false)] public class SortedList<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable可以看出SortedList不仅具有字典的特性,还有集合,迭代的功能
[csharp] view plaincopyprint?using System; using System.Collections.Generic; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { //Key必须唯一,如果不唯一可以考虑Lookup<TKey,TElement> SortedList<int, String> sList = new SortedList<int, string>(); sList.Add(, "张三"); sList.Add(, "李四"); sList.Add(, "王五"); sList.Add(, "田六"); sList.Add(, "赵七"); foreach (KeyValuePair<int, String> item in sList) { Console.WriteLine("key=" item.Key.ToString() ";value=" item.Value); } Console.Read(); } } }六、字典
字典是很复杂的数据结构,允许通过key来查找,字典可以自由添加、删除元素,没有集合由于移动元素导致的开销。
[csharp] view plaincopyprint?[Serializable] [DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))] [DebuggerDisplay("Count = {Count}")] [ComVisible(false)] public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback可以看出字典也具有集合的特性,可以迭代
[csharp] view plaincopyprint?using System; using System.Collections.Generic; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { //Key必须唯一 Dictionary<int, String> dict = new Dictionary<int, string>(); dict.Add(, "张三"); dict.Add(1, "李四"); dict.Add(2, "王五"); dict.Add(, "田六"); dict.Add(, "赵七"); foreach (KeyValuePair<int, String> item in dict) { Console.WriteLine("key=" item.Key.ToString() ";value=" item.Value); } Console.Read(); } } }说到字典,顺便谈一下有序字典,与有序列表对应;SortedDictionary,SortedList,SortedSet
会根据Key进行排序
[csharp] view plaincopyprint?using System; using System.Collections.Generic; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { //Key必须唯一 SortedDictionary<int, String> dict = new SortedDictionary<int, string>(); dict.Add(, "张三"); dict.Add(1, "李四"); dict.Add(2, "王五"); dict.Add(, "田六"); dict.Add(, "赵七"); foreach (KeyValuePair<int, String> item in dict) { Console.WriteLine("key=" item.Key.ToString() ";value=" item.Value); } Console.Read(); } } } Hashtable(哈希表)的用法Hashtable Student = new Hashtable(); Student.Add("Kevin", ); Student.Add("Kevsef", ); Student.Add("Keafdan", ); Student.Add("afcvin", ); foreach (DictionaryEntry obj in Student) { Debug.LogError("Test: " obj.Key); Debug.LogError("Test: " obj.Value); Debug.LogError("Test: " Student.ContainsKey("Kevin")); Debug.LogError("Test: " Student.ContainsKey("")); }unity 读取和写入Excel中文出现乱码解决方法 在编辑器中读取和写入中文一切正常,发布出来只要是中文就会出现乱码解决方法:将C:ProgramFilesUnityEditorDataMonolibmonounity目录下的IN.dll和IN.CJK.d
Unity3D读取XML文档信息实例 Unity3D读取XML文档信息分类:Unity3DXMLC#--:人阅读评论(0)收藏举报Unity3DXML[csharp]viewplaincopyprint?usingSystem;usingUnityEngine;usingSystem.IO;usingSystem.Xml;using
Unity的WWW类的用法整理 Unity的WWW类的用法整理1.Unity的WWW类主要支持GET和POST两种方式。GET方式请求的内容会附在url的后面一起做为URL向服务器发送请求(请求的内容使用符号隔
标签: unity常用代码
本文链接地址:https://www.jiuchutong.com/biancheng/378840.html 转载请保留说明!友情链接: 武汉网站建设