但凡IT江湖俠士,算法與數據結構爲必修之課。早有前輩已經明確指出:程序=算法+數據結構 。要想在以後的江湖歷練中通關,數據結構必不可少。數據結構與算法相輔相成,亦是陰陽互補之法。java
說道數組,幾乎每一個IT江湖人士都不陌生,甚至過半人還會很自信覺的它很簡單。 的確,在菜菜所知道的編程語言中幾乎都會有數組的影子。不過它不只僅是一種基礎的數據類型,更是一種基礎的數據結構。若是你覺的對數組足夠了解,那能不能回答一下:golang
所謂數組,是相同的元素序列。數組是在程序設計中,爲了處理方便,把具備相同類型的若干元素按無序的形式組織起來的一種形式。算法
正如以上所述,數組在應用上屬於數據的容器。不過我仍是要補充兩點:編程
有線性結構固然就有非線性結構,好比以後咱們要介紹的二叉樹,圖 等等,這裏再也不展開~~~ c#
我相信全部人在使用數組的時候都知道數組能夠按照下標來訪問,例如 array[1] 。做爲一種最基礎的數據結構是什麼使數組具備這樣的隨機訪問方式呢?天性聰慧的你可能已經想到了:內存連續+相同數據類型。 如今咱們抽象一下數據在內存上分配的情景。數組
array[n]=array[0]+size*n緩存
以上是元素地址的運算,其中size爲每一個元素的大小,若是爲int類型數據,那size就爲4個字節。其實確切的說,n的本質是一個離首元素的偏移量,因此array[n]就是距離首元素n個偏移量的元素,所以計算array[n]的內存地址只需以上公式。 服務器
論證一下,若是下標從1開始計算,那array[n]的內存地址計算公式就會變爲:數據結構
array[n]=array[0]+size*(n-1)編程語言
對比很容易發現,從1開始編號比從0開始編號每次獲取內存地址都多了一次 減法運算,也就多了一次cpu指令的運行。這也是數組從0下標開始訪問一個緣由。
其實還有一種可能性,那就是全部現代編程語言的鼻祖:C語言,它是從0開始計數下標的,因此如今全部衍生出來的後代語言也就延續了這個傳統。雖然不符合人類的思想,可是符合計算機的原理。固然也有一些語言能夠設置爲不從下標0開始計算,這裏再也不展開,有興趣的能夠去搜索一下。
固然這裏有一個技巧:若是你的業務要求並非數組連續有序的,當在位置k插入元素的時候,只須要把k元素轉移到數組末尾,新元素插入到k位置便可。固然仔細沉思一下這種業務場景可能性過小了,數組均可以無序,我直接插入末尾便可,沒有必要非得在k位置插入把。~~
固然還有一個特殊場景:若是是屢次連續的k位置插入操做,咱們徹底能夠合併爲一次「批量插入」操做:把k以後的元素總體移動sum(插入次數)個位置,無需一個個位置移動,把三次操做的時間複雜度合併爲一次。
與插入對應的就有刪除操做,同理,刪除操做數組爲了保持連續性,也須要元素的移動。
綜上所述,數組在添加和刪除元素的場景下劣勢比較明顯,因此在具體業務場景下應該避免頻繁添加和刪除的操做。 2. 數組的連續性就要求建立數組的時候,內存必須有相應大小的連續區塊,若是不存在,數組就有可能出現建立失敗的現象。在某些高級語言中(好比c#,golang,java)就有可能引起一次GC(垃圾回收)操做,GC操做在系統運行中是很是昂貴的,有的語言甚至會掛起全部線程的操做,對外的表現就是「暫停服務」。 3. 數組要求全部元素爲同一個類型。在存儲數據維度,它可能算是一種劣勢,可是爲了按照下標快速查找元素,業務中這也是一種優點。仁者見仁智者見智而已。 4. 數組是長度固定的數據結構,因此在原始數組的基礎上擴容是不可能的,有的語言可能實現數組的「僞擴容」,爲何說是「僞」呢,由於原理實際上是建立了一個容量更大的數組來存放原數組元素,發生了數據複製的過程,只不過對於調用者而已透明而已。 5. 數組有訪問越界的可能。咱們按照下標訪問數組的時候若是下標超出了數組長度,在現代多數高級語言中,直接就會引起異常了,可是一些低級語言好比C 有可能會訪問到數組元素之外的數據,由於要訪問的內存地址確實存在。
咱們學習的每一個數據結構其實都有對應的適合場景,只不過是場景多少的問題,具體何時用,須要咱們對該數據結構的特性作深刻分析。 關於數組的特性,經過以上介紹能夠知道最大的一個亮點就是按照下標訪問,那有沒有具體業務映射這種特性呢?