C#常用數據結構


常碰到的幾種數據結構:Array,ArrayList,List,LinkedList,Queue,Stack,Dictionary<K,T>;
1.數組是最簡單的數據結構。其具有如下特點:
數組存儲在連續的內存上。
數組的內容都是相同類型。
數組可以直接通過下標訪問。
創建一個新的數組時將在 CLR 托管堆中分配一塊連續的內存空間,來盛放數量為size,類型為所聲明類型的數組元素。如果類型為值類型,則將會有size個未裝箱的該類型的值被創建。如果類型為引用類型,則將會有size個相應類型的引用被創建;
由於是在連續內存上存儲的,所以它的索引速度非常快,訪問一個元素的時間是恆定的也就是說與數組的元素數量無關,而且賦值與修改元素也很簡單。
但是有優點,那么就一定會伴隨着缺點。由於是連續存儲,所以在兩個元素之間插入新的元素就變得不方便。而且就像上面的代碼所顯示的那樣,聲明一個新的數組時,必須指定其長度,這就會存在一個潛在的問題,那就是當我們聲明的長度過長時,顯然會浪費內存,當我們聲明長度過短的時候,則面臨這溢出的風險。這就使得寫代碼像是投機,小匹夫很厭惡這樣的行為!針對這種缺點,下面隆重推出ArrayList。

2.ArrayList:
  為了解決數組創建時必須指定長度以及只能存放相同類型的缺點而推出的數據結構。ArrayList是System.Collections命名空間下的一部分,所以若要使用則必須引入System.Collections。正如上文所說,ArrayList解決了數組的一些缺點。
不必在聲明ArrayList時指定它的長度,這是由於ArrayList對象的長度是按照其中存儲的數據來動態增長與縮減的。
ArrayList可以存儲不同類型的元素。這是由於ArrayList會把它的元素都當做Object來處理。因而,加入不同類型的元素是允許的。
ArrayList可以存儲不同類型數據的原因是由於把所有的類型都當做Object來做處理,也就是說ArrayList的元素其實都是Object類型的;ArrayList不是類型安全的。因為把不同的類型都當做Object來做處理,很有可能會在使用ArrayList時發生類型不匹配的情況。如上文所訴,數組存儲值類型時並未發生裝箱,但是ArrayList由於把所有類型都當做了Object,所以不可避免的當插入值類型時會發生裝箱操作,在索引取值時會發生拆箱操作。
裝箱時,生成的是全新的引用對象,這會有時間損耗,也就是造成效率降低。那么為了解決ArrayList不安全類型與裝箱拆箱的缺點,所以出現了泛型的概念,作為一種新的數組類型引入。也是工作中經常用到的數組類型。和ArrayList很相似,長度都可以靈活的改變,最大的不同在於在聲明List集合時,我們同時需要為其聲明List集合內數據的對象類型,這點又和Array很相似,其實List內部使用了Array來實現,
這么做最大的好處就是:(1)即確保了類型安全;(2)也取消了裝箱和拆箱的操作;(3)它融合了Array可以快速訪問的優點以及ArrayList長度可以靈活變化的優點。
既然鏈表最大的特點就是存儲在內存的空間不一定連續,那么鏈表相對於數組最大優勢和劣勢就顯而易見了。

向鏈表中插入或刪除節點無需調整結構的容量。因為本身不是連續存儲而是靠各對象的指針所決定,所以添加元素和刪除元素都要比數組要有優勢。
鏈表適合在需要有序的排序的情境下增加新的元素,這里還拿數組做對比,例如要在數組中間某個位置增加新的元素,則可能需要移動移動很多元素,而對於鏈表而言可能只是若干元素的指向發生變化而已。
有優點就有缺點,由於其在內存空間中不一定是連續排列,所以訪問時候無法利用下標,而是必須從頭結點開始,逐次遍歷下一個節點直到尋找到目標。所以當需要快速訪問對象時,數組無疑更有優勢。
綜上,鏈表適合元素數量不固定,需要經常增減節點的情況。

在Queue這種數據結構中,最先插入在元素將是最先被刪除;反之最后插入的元素將最后被刪除,因此隊列又稱為“先進先出”(FIFO—first in first out)的線性表。通過使用Enqueue和Dequeue這兩個方法來實現對 Queue 的存取。
一些需要注意的地方:

先進先出的情景。
1、默認情況下,Queue的初始容量為32, 增長因子為2.0。
2、當使用Enqueue時,會判斷隊列的長度是否足夠,若不足,則依據增長因子來增加容量,例如當為初始的2.0時,則隊列容量增長2倍。

與Queue相對,當需要使用后進先出順序(LIFO)的數據結構時,我們就需要用到Stack了。
一些需要注意的地方:
后進先出的情景。
1、默認容量為10。
2、使用pop和push來操作。

字典:
提到字典就不得不說Hashtable哈希表以及Hashing(哈希,也有叫散列的),因為字典的實現方式就是哈希表的實現方式,只不過字典是類型安全的,也就是說當創建字典時,必須聲明key和item的類型,這是第一條字典與哈希表的區別;我們在對字典的操作中各種時間上的優勢都享受到了,那么它的劣勢到底在哪呢?對嘞,就是空間。以空間換時間,通過更多的內存開銷來滿足我們對速度的追求。在創建字典時,我們可以傳入一個容量值,但實際使用的容量並非該值。而是使用“不小於該值的最小質數來作為它使用的實際容量,最小是3。”,當有了實際容量之后,並非直接實現索引,而是通過創建額外的2個數組來實現間接的索引,即int[] buckets和Entry[] entries兩個數組(即buckets中保存的其實是entries數組的下標),這里就是第二條字典與哈希表的區別,還記得哈希沖突嗎?對,第二個區別就是處理哈希沖突的策略是不同的!字典會采用額外的數據結構來處理哈希沖突,這就是剛才提到的數組之一buckets桶了,buckets的長度就是字典的真實長度,因為buckets就是字典每個位置的映射,然后buckets中的每個元素都是一個鏈表,用來存儲相同哈希的元素,然后再分配存儲空間


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM