數組與鏈表對於每一門編程語言來講都是重要的數據結構之一。數組是一段內存連續的,有序的元素序列,大小固定,初始化時須要指定可承載的元素個數; 鏈表是非連續、非順序的存儲結構, 數據元素的順序是經過指針連接實現的。java
開發中選擇數組仍是鏈表,這就要結合場景和它們各自優缺點.編程
數組的內存是連續, 連續有什麼意義,它內存地址是連續的, 好比建立一個new Object[5], 假如第一個內存地址是init_address, 第二個地址就是init_address + 1。全部數組隨機訪問很快,訪問第某個元素,用初始的地址加上下標就能找到啦, 數組遍歷也很快。 數組的大小固定, 數組在元素刪除和添加就帶來一點麻煩,在實際開發中一般使用數組容器,好比java的ArrayList,ArrayList有個默認數組容量, 爲10。 ArrayList.add方法中當添加第11個元素時,須要擴容建立一個新的數組,還須要把原數組的元素複製到新的數組。假如 ArrayList當前有8個元素,當移除第5個元素時,並非簡單把第5個元素設置爲null, 還要把第6 - 8 個元素都往前挪移1位。當ArrayList的元素是int等基本類型,會涉及到裝箱和拆箱,相對與直接使用Int數組性能會稍微差一點,可是有時方便,犧牲一點性能也能夠。數組
鏈表的元素經過指針連接, 故大小是無限,只要不爆內存,不須要像數組那樣擴容。鏈表的添加和刪除就相對簡單點,下面以單鏈表爲例,添加一個元素,把上一個元素的next指針指向一個新的元素便可; 假如該鏈表有3個元素,當刪除第2個元素時,把第一個元素的next指針指向第3個元素。鏈表元素遍歷相對數組慢一點,並且隨機訪問第某個元素也相對麻煩,須要遍歷。瀏覽器
鏈表根據結構一般能夠分爲:單鏈表、雙向鏈表、循環鏈表。數據結構
單鏈表:併發
雙向鏈表:編程語言
循環鏈表:函數
單鏈表中有環:性能
上面圖中有個單鏈表中有環,須要注意一下,在使用單鏈表時,在遍歷過程, 以最後元素的next指針爲null做爲結束的標誌,可是若是出現如圖的狀況,就會出現死循環。對於鏈表的代碼實現,很少說,能夠看java中LinkedList類, LinkedList實現了雙向鏈表。線程
棧是一種操做受限的線性表, 僅容許在一端進行插入和刪除運算, 後進者先出,先進者後出。舉個形象點的例子,有個硬幣大的杯子,往杯子裏一個個地放硬幣, 全部取硬幣只能從頂部一個個取出。(不能倒,杯子用502黏住啦) 這裏的硬幣就是程序裏的元素,而這個杯子就是"棧"。
怎麼實現一個棧?
上面提到數組和鏈表均可以實現。以數組實現爲例,簡單描述一下,壓棧(意思是放一個元素)過程只要按順序依次放到數組的index裏,從index=0開始; 數組能夠訪問任意index的元素,而出棧(意思是取一個元素)只能從頂部出, 因此須要限制數組裏元素的訪問,取出時只能從裝有元素中最大index中取出便可。固然壓棧時數組也可能須要擴容,一些細節就很少說啦, java中Stack類就是一個實現棧的例子。
隊列也是一種操做受限的線性表, 只容許在表的一端進行刪除操做,而在另外一端進行插入操做,先進者先出。來個形象的例子,有個一根玻璃球大的水管, 傾斜着放(假設左邊高右邊低),在左邊不停地放入球,球就會從右邊出, 而這水管就能夠簡單理解爲"隊列"。隊列也可使用數組或者鏈表實現。
棧的應用場景很普遍,下面舉一些例子:
瀏覽器的前進和後退能夠用棧來實現, 一個標籤頁是一個棧,在打開一個網壓棧,在網頁中點一個連接,也就是前進,再壓棧,後退對應就是出棧。 瀏覽器有新建一個標籤或者在新的標籤裏打開頁面,就是建立一個新的棧,並把打開連接壓棧。
安卓應用的界面前進後退也是,有Activity棧,Fragment棧。
函數調用也能夠用棧實現,在進入被調用函數的時候,分配一段棧空間給這個函數的變量,在函數運行結束的時候,將棧頂復位,正好回到調用函數的做用域內。
表達式求值中應用,好比 4 + (6 - 12 + 2* 2) * 2計算。
表達式運算過以下圖所示:
隊列一般存在不一樣的類型,好比循環隊列,併發隊列,阻塞隊列等, 不一樣的隊列使用場景有所不一樣。