這篇文章我們來說說Java裡一個很重要的資料結構——線性表,還是這張圖,線性表對應着下圖裡的List。
紅框裡的内容就是線性表的大家族了,其中黃色部分是要重點了解的, 線性表裡的元素是按線性排列的(這裡的線性指邏輯上的) 線性表分為兩大類,分别是順序表和連結清單 :
一、順序表
順序表中的資料元素存儲是連續的,記憶體劃分的區域也是連續的。存儲結構如下圖:
我們的ArrayList底層是數組實作的,底層元素在記憶體中是按順序排列的, ArrayList 是Java中順序表的展現。
二、連結清單
連結清單在實體存儲上通常是非連續、非順序的方式存儲的,資料元素的邏輯順序是通過連結清單中的引用來實作的。
1、單向連結清單
很簡單,記憶體中的對象是随機分布的,對象不但存儲了張三、李四等資料,還持有一個next引用,指向下一個對象,來确定一組對象的邏輯順序。
2、循環連結清單
也很簡單,和單向連結清單一樣,隻不過最後一個對象的next又指向了第一個對象。
3、雙向連結清單
不但持有next引用,指向下一個對象,還持有一個prev引用,指向上一個對象。
記住雙向連結清單這個圖,很重要,下一篇文章我們要講的LinkedList就是以雙向連結清單的方式實作的。
三、棧和隊列
棧和隊列是兩種比較特殊的線性表。
1、棧
棧是一種操作受限制的線性表。其限制是僅允許線上性表的尾部進行添加和删除操作,這一端被稱為棧頂,另一端稱為棧底。向一個棧添加新元素叫 壓棧 ,删除元素又稱為 出棧 。
如上圖,把趙六放入到棧中叫壓棧,不放入趙六,直接取出(删除)王五的過程叫出棧,隻能從棧頂放入和删除元素。本文第一張圖裡的 Stack 就是棧在Java中的實作。舉個例子,最後洗好的盤子都是疊放在最上面的,但每次用的時候都是從最上面拿,最先洗好的盤子反而不容易用到。
2、隊列
隊列也是一種操作受限制的線性表。隻能從頭部删除(取出)元素,從隊尾添加元素,進行删除操作的端稱為隊頭。
看上面的圖,隻能從隊尾添加元素,隊頭取出(删除)元素。本文第一張圖裡的 Queue 就是隊列的展現,Queue是基于連結清單來展現的。注意,Queue是一個接口,直接寫如下代碼是會報錯的
Queue queue = new Queue();//會報錯,Queue是接口,不允許執行個體化
正确的用法是
Queue queue = new LinkedList();// 正确的用法,基于連結清單來實作
隊列的連結清單實作是通過子類LinkedList來實作的,Queue接口收窄了LinkedList的通路權限,隻提供從隊尾,隊頭等的操作。
為了加深大家的印象,我舉一個例子,惡心了一點,但保證大家能記住, 大家在喝啤酒的過程中,正常去廁所小解的,這個過程叫做隊例。喝多了吐出來的過程,叫做棧 。