CSDN 的小夥伴們,大家好,我是沉默的王二。
假期結束了,需要快速切換到工作的狀态投入到新的一天當中。放假的時候痛快地玩耍,上班的時候積極的工作,這應該是我們大多數“現代人”該有的生活狀态。
今天我們來學一下資料結構方面的知識,對紮實 Java 的基本功非常有用,學會了就會有一種自帶大佬的感覺,嘿嘿。資料結構,也就是 Data Structure,是一種存儲資料的結構體,資料與資料之間存在着一定的關系,這樣的關系有資料的邏輯關系、資料的存儲關系和資料的運算關系。
在 Java 中,資料結構一般可以分為兩大類:線性資料結構和非線性資料結構。哈哈,這個非字很有靈魂吧?
先來說線性資料結構吧。
1)數組
一眼看上去就知道的,像 String []、int [] 這種;還有需要看兩眼才能看透的(看源碼了),像 ArrayList,内部對數組進行了封裝。
數組這種資料結構最大的好處,就是可以根據下标(或者叫索引)進行操作,插入的時候可以根據下标直接插入到具體的位置,但與此同時,後面的元素就需要全部向後移動,需要移動的資料越多,就越累。
假設現在已經有了一個 ArrayList 了,準備在第 4 個位置(下标為 3)上添加一個元素 55。

此時 ArrayList 中第 5 個位置以後的元素将會向後移動。
準備把 23 從 ArrayList 中移除。
此時下标為 7、8、9 的元素往前挪。
簡單總結一下 ArrayList 的時間複雜度,友善大家在學習的時候作為參考。
1、通過下标(也就是 get(int index))通路一個元素的時間複雜度為 O(1),因為是直達的,無論資料增大多少倍,耗時都不變。
2、添加一個元素(也就是 add())的時間複雜度為 O(1),因為直接添加到末尾。
3、删除一個元素的時間複雜度為 O(n),因為要周遊清單,資料量增大幾倍,耗時也增大幾倍。
4、查找一個未排序的清單時間複雜度為 O(n),因為要周遊清單;查找排序過的清單時間複雜度為 O(log n),因為可以使用二分查找法,當資料增大 n 倍時,耗時增大 logn 倍(這裡的 log 是以 2 為底的,每找一次排除一半的可能)。
2)連結清單
連結清單在實體存儲空間是不連續的,但每個節點要麼知道它的下一個節點是誰,要麼知道它的上一個節點是誰,仿佛就像我們之間隔着千山萬水,卻心有靈犀一點鍊。像 LinkedList 就是最典型的連結清單結構,通過引用互相連結。
LinkedList 中的每一個元素都可以稱之為節點(Node),每一個節點都包含三個項目:其一是元素本身,其二是指向下一個元素的引用位址,其三是指向上一個元素的引用位址。
LinkedList 看起來就像下面這個樣子:
第一個節點由于沒有前一個節點,是以 prev 為 null;
最後一個節點由于沒有後一個節點,是以 next 為 null;
這是一個雙向連結清單,每一個節點都由三部分組成,前後節點和值。
相比 ArrayList,LinkedList 有以下優勢:
1、LinkedList 允許記憶體進行動态配置設定,這就意味着記憶體配置設定是由編譯器在運作時完成的,我們無需在 LinkedList 聲明的時候指定大小。
2、LinkedList 不需要在連續的位置上存儲元素,因為節點可以通過引用指定下一個節點或者前一個節點。也就是說,LinkedList 在插入和删除元素的時候代價很低,因為不需要移動其他元素,隻需要更新前一個節點和後一個節點的引用位址即可。
3)棧
棧是一種非常有用的資料結構,它就像一摞盤子,第一個放在最下面,第二個放在第一個上面,第三個放在第二個上面,最後一個放在最上面。棧遵循後進先出的原則,也就是“Last In First Out”(簡稱 LIFO)——最後的一個進的,最先出去。
對于棧這樣一個資料結構來說,它有兩個常見的動作:
push,中文釋義有很多種,我個人更喜歡叫它“壓入”,非常形象。當我們要把一個資料放入棧的頂部,這個動作就叫做 push。
pop,同樣的,我個人更喜歡叫它“彈出”,帶有很強烈的動畫效果,有沒有?當我們要從棧中移除一個資料時,這個動作就叫做 pop。
4)隊列
隊列,隻允許在隊尾添加資料,隊首移除資料。隊列在 Java 中的出現頻率非常高,有各種不同的類來滿足不同的場景需求。像優先級隊列 PriorityQueue、延時隊列 DelayQueue 等等。隊列遵循的是 First In First Out,縮寫為 FIFO,也就是先進先出,第一個進入隊列的第一個先出來。