C#常見的數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu):
1.Set集合,純粹的容器,無需存儲(chǔ),就是一個(gè)容器
2.線型結(jié)構(gòu):在存儲(chǔ)的時(shí)候,一對(duì)一存儲(chǔ)
3.樹形結(jié)構(gòu):表達(dá)式目錄樹(二叉樹)、菜單結(jié)構(gòu):一對(duì)多
4.圖形結(jié)構(gòu):擴(kuò)撲圖、網(wǎng)狀結(jié)構(gòu)(地圖開發(fā),用C#高級(jí)–常用數(shù)據(jù)結(jié)構(gòu)
一.線程結(jié)構(gòu)1.線程結(jié)構(gòu):Array/ArrayList/List/LinkedList/Queue/Stack/HastSet/SortedSer/Hashtable/SortedListDictionaty/SortedDictionary2.數(shù)組:內(nèi)存連續(xù)儲(chǔ)存,節(jié)約空間,可以索引訪問,讀取快,增刪慢Array:在內(nèi)存上連續(xù)分配的,而且元素類型是一樣的可以坐標(biāo)訪問,讀取快---增減慢,長(zhǎng)度不變ArrayList:在以前的開發(fā)中使用不較多,不定長(zhǎng)度,連續(xù)分配的元素沒有限制,任何元素都是當(dāng)成Object處理,如果是值類型,會(huì)有裝箱操作讀取快,增刪慢List:是Array,內(nèi)存上都是連續(xù)擺放,不定長(zhǎng)度,泛型,保證類型安全,避免裝箱拆箱 性能也比ArrayList高讀取快,增刪慢以上特點(diǎn):讀取快,增刪相對(duì)慢3.非連續(xù)擺放,存儲(chǔ)數(shù)據(jù)+地址,找數(shù)據(jù)的話就只能順序查找,讀取慢,增刪快3.1.LinkedList:泛型的特點(diǎn):鏈表,元素不連續(xù)分配,每個(gè)元素都有記錄前后節(jié)點(diǎn),節(jié)點(diǎn)值可以重復(fù)能不能以下標(biāo)訪問:不能沒找元素只能遍歷,查找不方便增刪 就比較方便LinkedList<int> node123 = linkedList.Find(123);得到節(jié)點(diǎn)3.2.Queue 就是鏈表 先進(jìn)先出 放任務(wù)延遲執(zhí)行,A不斷寫入日志任務(wù) B不斷獲取任務(wù)去執(zhí)行Queue queue = new Queue();queue.Equals(); //添加數(shù)據(jù)queue.Dequeue(); //獲取并移除數(shù)據(jù)3.3.Stack 就是鏈表 先進(jìn)先出 解析表達(dá)式目錄樹,先產(chǎn)出的數(shù)據(jù)后使用,操作記錄為命令,撤銷的時(shí)候是倒序Stack stack = new Stack();stack.Push();//添加數(shù)據(jù)stack.Pop();//獲取并移除數(shù)據(jù)二.Set純粹的集合,容器,東西丟進(jìn)去,唯一性,無序的1.集合:hash分布,元素間沒有關(guān)系,動(dòng)態(tài)增加容量,去重統(tǒng)計(jì)用戶IP:IP投票 交叉并補(bǔ)---二次好友/間接關(guān)注/粉絲合集2. 排序的集合:去重 而且排序統(tǒng)計(jì)排名 -- 沒統(tǒng)計(jì)一個(gè)就丟進(jìn)集合里IComparer<T> comparer 自定義對(duì)象的排序,就用這個(gè)指定3.Hashtable Key-value 體積可以動(dòng)態(tài)增加 拿著Key計(jì)算一個(gè)地址,然后放入Key-valueobject - 裝箱拆箱 如果不同的key得到相同的地址,第二個(gè)在前面地址上+1 浪費(fèi)了空間,Hashtable是基于數(shù)組實(shí)現(xiàn)4.線程安全ConcurrentQueue 線程安全版本的QueueConcurrentStack 線程安全版本的StackConcurrentBag 線程安全的對(duì)象集合ConcurrentDictionary 線程安全的DictionaryBlockingCollection
一、常見的數(shù)據(jù)結(jié)構(gòu)
1、集合[Set]
2、線性結(jié)構(gòu)
3、樹形結(jié)構(gòu)
4、圖形結(jié)構(gòu)
二、Array/ArrayList/List
內(nèi)存上連續(xù)存儲(chǔ),節(jié)約空間,可以索引訪問,讀取快,增刪慢
1、Array
元素類型是一樣的,定長(zhǎng)
int[] list = new int[3];list[0] = 123;string[] stringArray = new string[] { “123”, “234” };for (int i = 0; i < list.Length; i++){Console.WriteLine(list[i]);}
2、ArrayList
元素沒有類型限制,任何元素都是當(dāng)成object處理,如果是值類型,會(huì)有裝箱操作,不定長(zhǎng)
ArrayList list = new ArrayList();//增加元素,增加長(zhǎng)度list.Add(“張三”);list.Add(“Is”);list.Add(32);//索引賦值,不會(huì)增加長(zhǎng)度,索引超出長(zhǎng)度直接報(bào)錯(cuò)list[2] = 26;list.AddRange(new ArrayList() { “李四”,135});//刪除數(shù)據(jù)list.RemoveAt(0);list.Remove(“張三”);list.RemoveRange(0, 1);//index,countfor (int i = 0; i < list.Count; i++){Console.WriteLine(list[i]);}//轉(zhuǎn)換成Arraryobject[] list2 = (object[])list.ToArray(typeof(object));object[] list3 = new object[list.Count];list.CopyTo(list3);
3、List
也是Array,泛型,保證類型安全,避免裝箱拆箱,性能比Arraylist高,不定長(zhǎng)
List list = new List();list.Add(123);list.Add(123);//list.Add(“123”);類型確定,類型安全,不同類型無法添加list[0] = 456;for (int i = 0; i < list.Count; i++){Console.WriteLine(list[i]);}
三、LinkedList/Queue/Stack
非連續(xù)存儲(chǔ),存儲(chǔ)數(shù)據(jù)和地址,只能順序查找,讀取慢,增刪快
1、LinkedList
鏈表,泛型,保證類型安全,避免裝箱拆箱,元素不連續(xù)分配,每個(gè)元素都記錄前后節(jié)點(diǎn),不定長(zhǎng)
LinkedList list = new LinkedList();//list[3] //不能索引訪問list.AddFirst(123);//在最前面添加list.AddLast(456); //在最后面添加//是否包含元素bool isContain = list.Contains(123);//元素123的位置 從頭查找LinkedListNode node123 = list.Find(123);//某節(jié)點(diǎn)前后添加list.AddBefore(node123, 123);list.AddAfter(node123, 9);//移除list.Remove(456);list.Remove(node123);list.RemoveFirst();list.RemoveLast();foreach (var item in list){Console.WriteLine(item);}//清空list.Clear();
2、Queue
隊(duì)列,就是鏈表,先進(jìn)先出
Queue numbers = new Queue();//入隊(duì)列numbers.Enqueue(“one”);numbers.Enqueue(“two”);numbers.Enqueue(“two”);numbers.Enqueue(“three”);numbers.Enqueue(“four”);foreach (string number in numbers){Console.WriteLine(number);}//移除并返回隊(duì)首元素Console.WriteLine(" D e q u e u e n u m b e r s . D e q u e u e ( ) " ) ; f o r e a c h ( s t r i n g n u m b e r i n n u m b e r s ) C o n s o l e . W r i t e L i n e ( n u m b e r ) ; / / 不移除返回隊(duì)首元素 C o n s o l e . W r i t e L i n e ( "Dequeue {numbers.Dequeue()}"); foreach (string number in numbers) { Console.WriteLine(number); } //不移除返回隊(duì)首元素 Console.WriteLine("Dequeuenumbers.Dequeue()");foreach(stringnumberinnumbers)Console.WriteLine(number);//不移除返回隊(duì)首元素Console.WriteLine(“Peek { numbers.Peek()}”);foreach (string number in numbers){Console.WriteLine(number);}//拷貝一個(gè)隊(duì)列Queue queueCopy = new Queue(numbers.ToArray());foreach (string number in queueCopy){Console.WriteLine(number);}//判斷包含元素Console.WriteLine(" q u e u e C o p y . C o n t a i n s ( f ¨ o u r ) ¨ = q u e u e C o p y . C o n t a i n s ( " f o u r " ) " ) ; / / 清空隊(duì)列 q u e u e C o p y . C l e a r ( ) ; C o n s o l e . W r i t e L i n e ( "queueCopy.Contains(\"four\") = {queueCopy.Contains("four")}"); //清空隊(duì)列 queueCopy.Clear(); Console.WriteLine("queueCopy.Contains(f¨our)¨=queueCopy.Contains("four")");//清空隊(duì)列queueCopy.Clear();Console.WriteLine(“queueCopy.Count = {queueCopy.Count}”);
3、Stack
棧,就是鏈表,先進(jìn)后出
Stack numbers = new Stack();//入棧numbers.Push(“one”);numbers.Push(“two”);numbers.Push(“two”);numbers.Push(“three”);numbers.Push(“four”);numbers.Push(“five”);foreach (string number in numbers){Console.WriteLine(number);}//獲取并出棧Console.WriteLine(" P o p n u m b e r s . P o p ( ) " ) ; f o r e a c h ( s t r i n g n u m b e r i n n u m b e r s ) C o n s o l e . W r i t e L i n e ( n u m b e r ) ; / / 獲取不出棧 C o n s o l e . W r i t e L i n e ( "Pop {numbers.Pop()}"); foreach (string number in numbers) { Console.WriteLine(number); } //獲取不出棧 Console.WriteLine("Popnumbers.Pop()");foreach(stringnumberinnumbers)Console.WriteLine(number);//獲取不出棧Console.WriteLine(“Peek { numbers.Peek()}”);foreach (string number in numbers){Console.WriteLine(number);}//拷貝一個(gè)棧Stack stackCopy = new Stack(numbers.ToArray());foreach (string number in stackCopy){Console.WriteLine(number);}//判斷包含元素Console.WriteLine(" s t a c k C o p y . C o n t a i n s ( f ¨ o u r ) ¨ = s t a c k C o p y . C o n t a i n s ( " f o u r " ) " ) ; / / 清空棧 s t a c k C o p y . C l e a r ( ) ; C o n s o l e . W r i t e L i n e ( "stackCopy.Contains(\"four\") = {stackCopy.Contains("four")}"); //清空棧 stackCopy.Clear(); Console.WriteLine("stackCopy.Contains(f¨our)¨=stackCopy.Contains("four")");//清空棧stackCopy.Clear();Console.WriteLine(“stackCopy.Count = {stackCopy.Count}”);
四、HashSet/SortedSet
純粹的集合,容器,唯一,無序
1、HashSet
集合,hash分布,動(dòng)態(tài)增加容量,去重?cái)?shù)據(jù)或者引用類型地址
應(yīng)用場(chǎng)景:去重可以統(tǒng)計(jì)用戶IP,計(jì)算集合元素的交叉并補(bǔ),二次好友/間接關(guān)注/粉絲合集
HashSet hashSetA = new HashSet();hashSetA.Add(“123”);hashSetA.Add(“456”);//系統(tǒng)為了提高性能,減少內(nèi)存占用,字符串是設(shè)計(jì)成池化的,字符串也是引用類型的,同一個(gè)字符串地址是相同的,所以會(huì)去重string s1 = “12345”;hashSetA.Add(s1);string s2 = “12345”;hashSetA.Add(s2);//hashSet[0];//不能使用索引訪問//判斷包含元素Console.WriteLine($“hashSetA.Contains(“12345”) = {hashSetA.Contains(“12345”)}”);//集合的計(jì)算:交叉并補(bǔ)Console.WriteLine(“集合A******************”);foreach (var item in hashSetA){Console.WriteLine(item);}HashSet hashSetB = new HashSet();hashSetB.Add(“123”);hashSetB.Add(“789”);hashSetB.Add(“12435”);Console.WriteLine(“集合B******************”);foreach (var item in hashSetB){Console.WriteLine(item);}Console.WriteLine(“交:屬于A且屬于B的元素******************”);//拷貝一個(gè)集合HashSet hashSetCopy4 = new HashSet(hashSetB);hashSetCopy4.IntersectWith(hashSetA);foreach (var item in hashSetCopy4){Console.WriteLine(item);}Console.WriteLine(“差:屬于B,不屬于A的元素******************”);HashSet hashSetCopy3 = new HashSet(hashSetB);hashSetCopy3.ExceptWith(hashSetA);foreach (var item in hashSetCopy3){Console.WriteLine(item);}Console.WriteLine(“并:屬于A或者屬于B的元素******************”);HashSet hashSetCopy2 = new HashSet(hashSetB);hashSetCopy2.UnionWith(hashSetA);foreach (var item in hashSetCopy2){Console.WriteLine(item);}Console.WriteLine(“補(bǔ):AB的并集去掉AB的交集******************”);HashSet hashSetCopy = new HashSet(hashSetB);hashSetCopy.SymmetricExceptWith(hashSetA);foreach (var item in hashSetCopy){Console.WriteLine(item);}//轉(zhuǎn)換成List集合hashSetA.ToList();//清空集合hashSetA.Clear();//添加對(duì)象引用去重HashSet peoples = new HashSet();People people = new People(){Id = 123,Name = “小菜”};People people1 = new People(){Id = 123,Name = “小菜”};peoples.Add(people);peoples.Add(people1);//內(nèi)容相同也是不同的對(duì)象peoples.Add(people1);//同一個(gè)對(duì)象會(huì)去重foreach (var item in peoples){Console.WriteLine(item);}
2、SortedSet
排序的集合,去重,排序
應(yīng)用場(chǎng)景:名字排序
SortedSet sortedSet = new SortedSet();sortedSet.Add(“123”);sortedSet.Add(“689”);sortedSet.Add(“456”);sortedSet.Add(“12435”);sortedSet.Add(“12435”);sortedSet.Add(“12435”);//判斷包含元素Console.WriteLine($“sortedSet.Contains(“12435”) = {sortedSet.Contains(“12435”)}”);//轉(zhuǎn)換成List集合sortedSet.ToList();//清空集合sortedSet.Clear();
五、Hashtable/Dictionary/SortedDictionary/SortedList
讀取,增刪都快,key-value,一段連續(xù)有限空間放value,基于key散列計(jì)算得到地址索引,讀取增刪都快,開辟的空間比用到的多,hash是用空間換性能
基于key散列計(jì)算得到地址索引,如果Key數(shù)量過多,散列計(jì)算后,肯定會(huì)出現(xiàn)散列沖突(不同的key計(jì)算出的索引相同)
散列沖突之后,據(jù)存儲(chǔ)就是在索引的基礎(chǔ)上往后找空閑空間存放,讀寫增刪性能就會(huì)下降,dictionary在3W條左右性能就開始下降
1、Hashtable
哈希表,元素沒有類型限制,任何元素都是當(dāng)成object處理,存在裝箱拆箱
Hashtable table = new Hashtable();table.Add(“123”, “456”);//table.Add(“123”, “456”);//key相同 會(huì)報(bào)錯(cuò)table[234] = 456;table[234] = 567;table[32] = 4562;foreach (DictionaryEntry item in table){Console.WriteLine(KaTeX parse error: Expected 'EOF', got '}' at position 39: …item.Value}"); }? //移除元素 table.R…“table.ContainsKey(“123”) ={table.ContainsKey(“123”) }”);Console.WriteLine($“table.ContainsValue(“456”) ={table.ContainsValue(“456”) }”);//清空table.Clear();
2、Dictionary
字典,支持泛型,有序的
Dictionary<int, string> dic = new Dictionary<int, string>();dic.Add(1, “HaHa”);dic.Add(5, “HoHo”);dic.Add(3, “HeHe”);dic.Add(2, “HiHi”);foreach (var item in dic){Console.WriteLine($“Key:{item.Key} Value:{item.Value}”);}
3、SortedDictionary
字典,支持泛型,有序
SortedDictionary<int, string> dic = new SortedDictionary<int, string>();dic.Add(1, “HaHa”);dic.Add(5, “HoHo”);dic.Add(3, “HeHe”);dic.Add(2, “HiHi”);dic.Add(4, “HuHu1”);dic[4] = “HuHu”;foreach (var item in dic){Console.WriteLine($“Key:{item.Key} Value:{item.Value}”);}
4、SortedList
排序列表是數(shù)組和哈希表的組合,使用索引訪問各項(xiàng),則它是一個(gè)動(dòng)態(tài)數(shù)組,如果您使用鍵訪問各項(xiàng),則它是一個(gè)哈希表。集合中的各項(xiàng)總是按鍵值排序。
SortedList sortedList = new SortedList();sortedList.Add(“First”, “Hello”);sortedList.Add(“Second”, “World”);sortedList.Add(“Third”, “!”);sortedList[“Third”] = “~~”;sortedList.Add(“Fourth”, “!”);//使用鍵訪問sortedList[“Fourth”] = “!!!”;//可以用索引訪問Console.WriteLine(sortedList.GetByIndex(0));//獲取所有keyvar keyList = sortedList.GetKeyList();//獲取所有valuevar valueList = sortedList.GetValueList();//用于最小化集合的內(nèi)存開銷sortedList.TrimToSize();//刪除元素sortedList.Remove(“Third”);sortedList.RemoveAt(0);//清空集合sortedList.Clear();
六、迭代器模式
1、迭代器模式
迭代器模式是設(shè)計(jì)模式中行為模式(behavioral pattern)的一種。迭代器模式使得你能夠使用統(tǒng)一的方式獲取到序列中的所有元素,而不用關(guān)心是其類型是array,list,linked list或者是其他什么序列結(jié)構(gòu)。這一點(diǎn)使得能夠非常高效的構(gòu)建數(shù)據(jù)處理通道(data pipeline)。
在.NET中,迭代器模式被IEnumerator和IEnumerable及其對(duì)應(yīng)的泛型接口所封裝。
IEnumerable:如果一個(gè)類實(shí)現(xiàn)了IEnumerable接口,那么就能夠被迭代,IEnumerable接口定義了GetEnumerator方法將返回IEnumerator接口的實(shí)現(xiàn),它就是迭代器本身。
IEnumerator:IEnumerator接口定義了訪問數(shù)據(jù)的統(tǒng)一屬性和方法object Current:當(dāng)前訪問的數(shù)據(jù)對(duì)象,bool MoveNext():移動(dòng)到下一個(gè)位置訪問下一個(gè)數(shù)據(jù)的方法,并判斷是否有下一個(gè)數(shù)據(jù);void Reset():數(shù)據(jù)列表改變或者重新訪問重置位置
Console.WriteLine(“迭代器模式–各自遍歷***”);//數(shù)組的遍歷int[] list = new int[3] { 1, 2, 3 };for (int i = 0; i < list.Length; i++){Console.WriteLine(list[i]);}//List遍歷List list2 = new List() { 1, 2, 3 };for (int i = 0; i < list2.Count; i++){Console.WriteLine(list[i]);}Console.WriteLine(“迭代器模式–foreach通用遍歷***”);//通用遍歷foreach (var item in list){Console.WriteLine(item);}foreach (var item in list2){Console.WriteLine(item);}Console.WriteLine(“迭代器模式–迭代器遍歷***”);//迭代器訪問真相var list3 = list.GetEnumerator();while (list3.MoveNext()){Console.WriteLine(list3.Current);}//迭代器訪問真相var list4 = list2.GetEnumerator();while (list4.MoveNext()){Console.WriteLine(list4.Current);}
2、Yield原理
Yield關(guān)鍵字其實(shí)是一種語法糖,最終還是通過實(shí)現(xiàn)IEnumberable、IEnumberable、IEnumberator和IEnumberator接口實(shí)現(xiàn)的迭代功能,含有yield的函數(shù)說明它是一個(gè)生成器,而不是普通的函數(shù)。Yield必須配合IEnumerable使用。
當(dāng)程序運(yùn)行到y(tǒng)ield return這一行時(shí),該函數(shù)會(huì)返回值,并保存當(dāng)前域的所有變量狀態(tài),等到該函數(shù)下一次被調(diào)用時(shí),會(huì)從上一次中斷的地方繼續(xù)往下執(zhí)行,直到函數(shù)正常執(zhí)行完成。
當(dāng)程序運(yùn)行到y(tǒng)ield break這一行時(shí),程序就結(jié)束運(yùn)行退出。
方法定義
// Yield方法public static IEnumerable Yield(){for (int i = 0; i < 5; i++){if (i > 2 && i < 4){yield break;}else{yield return Get(i);Console.WriteLine($“Yield執(zhí)行第{i + 1}次”);}}}////// 普通方法的遍歷//////public static IEnumerable Common(){List intList = new List();for (int i = 0; i < 5; i++){intList.Add(Get(i));Console.WriteLine($“Common執(zhí)行第{i + 1}次”);}return intList;}private static int Get(int num){Thread.Sleep(500);return num * DateTime.Now.Second;}
程序調(diào)用
var yieldlist = Yield();foreach (var item in yieldlist){Console.WriteLine(item);//按需獲取,要一個(gè)拿一個(gè)}var commonlist = Common();foreach (var item in commonlist){Console.WriteLine(item);//先全部獲取,然后一起返回}
運(yùn)行結(jié)果
0Yield執(zhí)行第1次19Yield執(zhí)行第2次40Yield執(zhí)行第3次Common執(zhí)行第1次Common執(zhí)行第2次Common執(zhí)行第3次Common執(zhí)行第4次Common執(zhí)行第5次021426688
本文來自博客園,作者:{春光牛牛,yak},轉(zhuǎn)載請(qǐng)注明原文鏈接:http://www.rzrgm.cn/yakniu/p/17143971.html
歡迎各位大佬們?cè)u(píng)論指正
QQ討論群:610129902


浙公網(wǎng)安備 33010602011771號(hào)