聊聊數組與鏈表,棧與隊列

數組與鏈表

數組與鏈表對於每一門編程語言來講都是重要的數據結構之一。數組是一段內存連續的,有序的元素序列,大小固定,初始化時須要指定可承載的元素個數; 鏈表是非連續、非順序的存儲結構, 數據元素的順序是經過指針連接實現的。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個元素。鏈表元素遍歷相對數組慢一點,並且隨機訪問第某個元素也相對麻煩,須要遍歷。瀏覽器

鏈表根據結構一般能夠分爲:單鏈表、雙向鏈表、循環鏈表。數據結構

單鏈表:併發

single-link

雙向鏈表:編程語言

double-link

循環鏈表:函數

circle-link

單鏈表中有環:性能

single-link-with-circle

上面圖中有個單鏈表中有環,須要注意一下,在使用單鏈表時,在遍歷過程, 以最後元素的next指針爲null做爲結束的標誌,可是若是出現如圖的狀況,就會出現死循環。對於鏈表的代碼實現,很少說,能夠看java中LinkedList類, LinkedList實現了雙向鏈表。線程

棧與隊列

棧是一種操做受限的線性表, 僅容許在一端進行插入和刪除運算, 後進者先出,先進者後出。舉個形象點的例子,有個硬幣大的杯子,往杯子裏一個個地放硬幣, 全部取硬幣只能從頂部一個個取出。(不能倒,杯子用502黏住啦) 這裏的硬幣就是程序裏的元素,而這個杯子就是"棧"。

怎麼實現一個棧?

上面提到數組和鏈表均可以實現。以數組實現爲例,簡單描述一下,壓棧(意思是放一個元素)過程只要按順序依次放到數組的index裏,從index=0開始; 數組能夠訪問任意index的元素,而出棧(意思是取一個元素)只能從頂部出, 因此須要限制數組裏元素的訪問,取出時只能從裝有元素中最大index中取出便可。固然壓棧時數組也可能須要擴容,一些細節就很少說啦, java中Stack類就是一個實現棧的例子。

隊列也是一種操做受限的線性表, 只容許在表的一端進行刪除操做,而在另外一端進行插入操做,先進者先出。來個形象的例子,有個一根玻璃球大的水管, 傾斜着放(假設左邊高右邊低),在左邊不停地放入球,球就會從右邊出, 而這水管就能夠簡單理解爲"隊列"。隊列也可使用數組或者鏈表實現。

棧與隊列應用場景

棧的應用場景很普遍,下面舉一些例子:

  • 瀏覽器的前進和後退能夠用棧來實現, 一個標籤頁是一個棧,在打開一個網壓棧,在網頁中點一個連接,也就是前進,再壓棧,後退對應就是出棧。 瀏覽器有新建一個標籤或者在新的標籤裏打開頁面,就是建立一個新的棧,並把打開連接壓棧。

  • 安卓應用的界面前進後退也是,有Activity棧,Fragment棧。

  • 函數調用也能夠用棧實現,在進入被調用函數的時候,分配一段棧空間給這個函數的變量,在函數運行結束的時候,將棧頂復位,正好回到調用函數的做用域內。

  • 表達式求值中應用,好比 4 + (6 - 12 + 2* 2) * 2計算。

表達式運算過以下圖所示:

stack_counter

隊列一般存在不一樣的類型,好比循環隊列,併發隊列,阻塞隊列等, 不一樣的隊列使用場景有所不一樣。

  • 阻塞隊列, 當隊列爲空的時候,從隊頭取數據會被阻塞, 直到隊列中有了數據才能返回;若是隊列已經滿了,那麼插入數據的操做也會被阻塞,直到隊列中有空閒位置後再插入數據,而後再返回。 阻塞隊列一般用在生產者消費者模型中,生產數據和消費數據的速率不一致,若是生產數據速度快一些,消費者處理不過來,就可能會致使數據丟失。這時候咱們就能夠用阻塞隊列來解決。
  • 隊列應用在線程池請求排隊的場景, 當線程池沒有空閒線程時,新的任務請求線程資源,線程池一般會使用隊列來存儲排隊的請求,爲何用隊列, 由於隊列先進先出,能夠比較公平處理排隊的請求。若是是使用鏈表的實現方式,能夠實現無限排隊的無界隊列, 可是可能會致使過多請求排隊,形成處理響應時間慢。若是使用數組的實現方式,是有界隊列, 當排隊請求滿了,接下來的請求會被拒絕。全部這兩種策略能夠看場景使用。
相關文章
相關標籤/搜索