上體育課的時候,老師說:你們站一隊,每個人記住自己是第幾個,我喊到幾,那個人就舉手,這就是數組。
老是說,你們每個人記住自己前面的人和后面的人,然后老師只知道第一人是誰。 然后你們各自由活動,老是要找某一個人,是不是每次都是從第一個開始往自己身后的人開始傳達?這就是鏈表。
老師說: 大家1,2,3,4報數,凡是報1,為1隊,凡是報2的為2隊。。。。 這就是散列(哈希)。而這個4就相當於預定義好的桶的個數。。
程序中,存放指定的數據最常用的數據結構有兩種:數組和鏈表。
數組和鏈表的區別:
1,數組是將元素在內存中連續存放。
鏈表中的元素在內存中不是順序存儲的,而是通過存在元素中的指針聯系到一起。
2,數組必須事先定義固定的長度,不能適應數據動態的增減的情況。當數據增加時,可能超出原先定義的元素個數;當數據減少時,造成內存浪費;
鏈表動態地進行存儲分配,可以適應數據動態地增減的情況。
3,(靜態)數組從棧中分配空間,對於程序員方便快速,但是自由度小;
鏈表從堆中分配空間,自由度大但是申請管理比較麻煩。
數組和鏈表在存儲數據方面到底誰好?根據數組和鏈表的特性,分兩種情況討論:
1,當進行數據查詢時,數組可以直接通過下標迅速訪問數組中的元素。
而鏈表則需要從第一個元素開始一直找到需要的元素位置,
顯然,數組的查詢效率會比鏈表的高。
2,當進行增加或刪除元素時,在數組中增加一個元素,需要移動大量元素,在內存中空出一個元素的空間,然后將要增加的元素放在其中。同樣,如果想刪除一個元素,需要移動大量去填掉被移動的元素,而鏈表只需改動元素中的指針即可實現增加或刪除元素。
那么哈希表,是既能具備數組的快速查詢的優點,又能融合鏈表方便快捷的增加刪除元素的優勢。
所謂的hash,簡單的說就是散列,即將輸入的數據通過hash函數得到一個key值,輸入的數據存儲到數組中下標的key值的數組單元中去。
數組和鏈表在存儲數據方面到底孰優孰劣呢?根據數組和鏈表的特性,分兩類情況討論。
一、當進行數據查詢時,數組可以直接通過下標迅速訪問數組中的元素。而鏈表則需要從第一個元素開始一直找到需要的元素位置,顯然,數組的查詢效率會比鏈表的高。
二、當進行增加或刪除元素時,在數組中增加一個元素,需要移動大量元 素,在內存中空出一個元素的空間,然后將要增加的元素放在其中。同樣,如果想刪除一個元素,需要移動大量元素去填掉被移動的元素。而鏈表只需改動元素中的指針即可實現增加或刪除元素。
那么,我們開始思考:有什么方式既能夠具備數組的快速查詢的優點又能融合鏈表方便快捷的增加刪除元素的優勢?HASH呼之欲出。
所謂的hash,簡單的說就是散列,即將輸入的數據通過hash函數得到一個key值,輸入的數據存儲到數組中下標為key值的數組單元中去。
我們發現,不相同的數據通過hash函數得到相同的key值。這時候,就產生了hash沖突。解決hash沖突的方式有兩種。一種是掛鏈式,也叫拉鏈法。掛鏈式的思想在產生沖突的hash地址指向一個鏈表,將具有相同的key值的數據存放到鏈表中。另一種是建立一個公共溢出區。將所有產生沖突的數據都存放到公共溢出區,也可以使問題解決。
hash表其實是結合了數組和鏈表的優點,進行的折中方案。平衡了數組和鏈表的優缺點。hash的具體實現有很多種,但是需要解決沖突的問題。
不相同的數據通過hash函數得到相同的key值。這時候,就產生了hash沖突。解決hash沖突的方式有兩種。一種是掛鏈式,也叫拉鏈法。掛鏈式的思想在產生沖突的hash地址指向一個鏈表,將具有相同的key值的數據存放到鏈表中。另一種是建立一個公共溢出區。將所有產生沖突的數據都存放到公共溢出區,也可以使問題解決。
數組(Array):
優點:查詢快,通過索引直接查找;有序添加,添加速度快,允許重復;
缺點:在中間部位添加、刪除比較復雜,大小固定,只能存儲一種類型的數據;
如果應用需要快速訪問數據,很少插入和刪除元素,就應該用數組。
鏈表(LinkedList):
優點:有序添加、增刪改速度快,對於鏈表數據結構,增加和刪除只要修改元素中的指針就可以了;
缺點:查詢慢,如果要訪問鏈表中一個元素,就需要從第一個元素開始查找;
如果應用需要經常插入和刪除元素,就應該用鏈表。
棧(Stack):
優點:提供后進先出的存儲方式,添加速度快,允許重復;
缺點:只能在一頭操作數據,存取其他項很慢;
隊列(Queue):
優點:提供先進先出的存儲方式,添加速度快,允許重復;
缺點:只能在一頭添加,另一頭獲取,存取其他項很慢;
哈希(Hash):
特點:散列表,不允許重復;
優點:如果關鍵字已知則存取速度極快;
缺點:如果不知道關鍵字則存取很慢,對存儲空間使用不充分;