數組、鏈表、堆棧和隊列


數據結構:是指相互之間存在一種或多種特定關係的數據元素的集合。聽起來是不是很抽象,簡單理解:數據結構就是描述對象間邏輯關係的學科。比如:隊列就是一種先進先出的邏輯結構,棧是一種先進後出的邏輯結構,家譜是一種樹形的邏輯結構!(初學數據結構的時候很不理解爲什麼有“棧”這個東西;隊列很容易理解---無論購物就餐都需要排隊;棧可以認爲就是個棧道---只允許一個人通過的小道,而且只能從一端進入,然後再從這端返回,比如你推了個箱子進去啦,第二個人也推個箱子進去,此時只能等後進來的這個人拉着箱子出去後,你才能退出。)

數據存儲結構:它是計算機的一個概念,簡單講,就是描述數據在計算機中存儲方式的學科;常用的數據存儲方式就兩種:順序存儲,非順序存儲!順序存儲就是把數據存儲在一塊連續的存儲介質(比如硬盤或內存)上----舉個例子:從內存中拿出第100個字節到1000個字節間的連續位置,存儲數據;數組就是典型的順序存儲!非順序存儲就是各個數據不一定存在一個連續的位置上,只要每個數據知道它前面的數據和後面的數據,就能把所有數據連續起來啦;鏈表就是典型的非順序存儲啦!


數組、鏈表、堆棧和隊列是最基本的數據結構,任何程序都會涉及到其中的一種或多種。

 

數組

     數組是最最基本的數據結構,很多語言都內置支持數組。數組是使用一塊連續的內存空間保存數據,保存的數據的個數在分配內存的時候就是確定的:

 

圖 1.1 包含 n 個數據的數組

     訪問數組中第 個數據的時間花費是 O(1) 但是要在數組中查找一個指定的數據則是 O(N)。當向數組中插入或者刪除數據的時候,最好的情況是在數組的末尾進行操作,時間複雜度是O(1) ,但是最壞情況是插入或者刪除第一個數據,時間複雜度是 O(N) 。在數組的任意位置插入或者刪除數據的時候,後面的數據全部需要移動,移動的數據還是和數據個數有關所以總體的時間複雜度仍然是 O(N) 

 

圖 1.2 向數組中插入數據

 

鏈表

     鏈表是在非連續的內存單元中保存數據,並且通過指針將各個內存單元鏈接在一起,最有一個節點的指針指向 NULL 。鏈表不需要提前分配固定大小存儲空間,當需要存儲數據的時候分配一塊內存並將這塊內存插入鏈表中。

     在鏈表中查找第 個數據以及查找指定的數據的時間複雜度是 O(N) ,但是插入和刪除數據的時間複雜度是 O(1) ,因爲只需要調整指針就可以:

 

圖 2.1 鏈表

 

圖 2.2 向鏈表中插入一個數據

 

圖 2.3 從鏈表中刪除一個數據

     向上面這樣的鏈表結構在插入和刪除的時候編程會比較困難,因爲需要記住當前節點的前一個節點,這樣才能完成插入和刪除。爲了簡便通常使用帶有頭節點的鏈表:

 

圖 2.4 帶有頭節點的單鏈表

     上面的鏈表是單鏈表,此外還有雙鏈表,就是節點中包含指向下一個節點的指針和指向上一個節點的指針:

 

 2.5 雙向鏈表

     不帶有頭節點的雙向鏈表在插入和刪除數據的時候也不會出現單鏈表那樣的問題。此外還有一種鏈表是循環鏈表,它是將雙向鏈表的頭尾相接:

 

圖 2.6 雙向循環鏈表

     向循環雙向鏈表和循環鏈表中插入或者從中刪除數據只是多移動幾個指針。

 

堆棧

     堆棧實現了一種後進先出的語義 (LIFO) 。可以使用數組或者是鏈表來實現它:

 

圖 3.1 堆棧

     對於堆棧中的數據的所有操作都是在棧的頂部完成的,只可以查看棧頂部的數據,只能夠向棧的頂部壓入數據,也只能從棧的頂部彈出數據。

 

隊列

     隊列實現了先入先出的語義 (FIFO) 。隊列也可以使用數組和鏈表來實現:

 

圖 4.1 隊列

         隊列只允許在隊尾添加數據,在隊頭刪除數據。但是可以查看隊頭和隊尾的數據。還有一種是雙端隊列,在兩端都可以插入和刪除:

 

圖 4.2 雙端隊列

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章