線性表結構:線性表:數組、鏈表、棧、隊列前端
1.數組:連續的內存空間。java
1.1 查找:隨機查找的時間複雜度爲O(1),注意,只是隨機查找(用下標的方式)。排序後的二分查找時間複雜度O(logn)數據庫
中間插入和刪除:須要搬移元素位置,時間複雜度爲O(n)編程
開頭和結尾插入和刪除:O(1)後端
插入優化技巧:若是條件容許,插入到第K個位置時,能夠把第K個位置的元素移動到最後,減小數據搬運數組
刪除優化技巧:若是條件容許,能夠幾個刪除一塊兒後,再搬移元素。(相似JVM的垃圾回收,標記清除法)
1.2 JAVA中的ArrayList封裝了數組,相比數組優點:動態擴容。瀏覽器
(1)擴容時,新建一個大的數組,而後數據拷貝到這個新的數組。緩存
(2)擴容大小:原來容量的1.5倍數據結構
(3)數組和ArrayList的選擇:通常使用ArrayList,可是對於底層框架的開發,須要把性能作到極致,能夠選擇數組。併發
1.3 二維數組能夠表示矩陣
針對稀疏矩陣的表示:若是直接表示會浪費存儲空間。能夠採用三項式來表示。
A(0,1)表示矩陣的行數
A(0,2)表示矩陣的列數
A(0,3)表示矩陣的非零項的總數
A(i,j,value) 表示非零的項。i從1開始,第i行第j列的值爲value
1.4 數組和多項式
P(x) = a0 + a1x + a2*x^2 + a3*x^3 + ... + + an*x^n
好比 2x^5 + 3x^4 + 5x^2 + 4x + 1
方法一:使用n+2長度的一維數組存儲,第一個元素是最大的指數n,其他元素按n遞減存儲多項式的係數。若是沒有的存儲0
A = {5,2,3,0,5,4,1} ,其中這裏沒有x^3的係數,因此第四項爲0
缺點:若是有x^100,那麼素組的長度爲100+1
方法二:只存儲多項式非零項。第一個元素爲多項式非零項的個數。
A = {5,2,5,3,4,5,2,4,1,1,0}
缺點:計算時可能會更復雜些
2.鏈表:不要求內存空間連續
2.1 插入和刪除:適合大量的操做 O(1);查詢: O(n)
2.2 JAVA中的LinkedList爲雙向鏈表,有next也有previous
LinkedList能夠實現棧、隊列以及雙端隊列等數據結構
LinkedList能夠實現LRU緩存機制
2.3 單向鏈表:指針和數據(第一個接節點是鏈表頭指針,最後一個指針設置爲null)
循環鏈表:最後一個指針指向鏈表頭部,從任何一個節點入手,能夠遍歷全部其餘節點
環形鏈表:一般應用於內存工做區與輸入/到處緩衝區
雙向鏈表:優點是能夠輕鬆找到先後節點
雙向循環鏈表
2.4 鏈表和多項式:和數組的方法同樣,只是鏈表實現的好處是適合多項式內容變更
2.5 環形鏈表能夠實現稀疏矩陣:優勢是矩陣變動時不須要大量移動數據
3.跳錶(跳躍表):經過多級索引使得鏈表可以實現二分查找,加速鏈表的隨機查詢效率,似於二分查找。
查詢(不支持隨機查詢):O(logn)
空間複雜度:O(n)
場景: Redis使用了跳錶。
HBase MemStore的也使用的跳錶。爲何呢?
HBase 屬於 LSM Tree 結構的數據庫,LSM Tree 結構的數據庫有個特色,實時寫入的數據先寫入到內存
內存達到閾值往磁盤 flush 的時候,會生成相似於 StoreFile 的有序文件,而跳錶剛好就是自然有序的
因此在 flush 的時候效率很高,並且跳錶查找、插入、刪除性能都很高,這應該是 HBase MemStore 內部存儲數據使用跳錶的緣由之一。
HBase 使用的是 java.util.concurrent 下的 ConcurrentSkipListMap()。
4.棧:先入後出,當作桶。(操做受限的數組或鏈表結構)
4.1 添加、刪除複雜度都是O(1);查詢: O(n)
4.2 能夠數組實現(順序棧)和鏈表實現(鏈式棧)(數組不利於大小動態變化,可是優勢是編程簡單)只須要一個top指針指向棧頂元素。
4.3 應用:瀏覽器前進後退
函數調用
表達式取值
5.隊列Queue:先入先出,通俗理解:排隊。(操做受限的數組或鏈表結構)
5.1 添加、刪除複雜度都是O(1);查詢: O(n)
在高級語言中,通常不用純粹的棧和隊列,java能夠用雙端隊列替代。
5.2 能夠數組(順序隊列)和鏈表(鏈式隊列)實現。
線程池中的各類策略:
鏈表實現:無界隊列,不合適響應時間敏感的。
數組實現:有界隊列,適合響應時間敏感的。
環形隊列與鏈式隊列的選擇:若是能夠肯定最大的大小,那麼選擇環形隊列。若是不能肯定,那麼選擇鏈式隊列。
5.3 須要兩個指針front和rear分別指向前端和後端。
5.4 應用:做業調度、磁盤的緩衝區。
5.5 雙端隊列Deque:兩邊均可以進出。兩邊都須要front和rear指針。
5.6 循環隊列 : MapReduce中Shuffle時使用了。
注意:環形隊列是使用數組實現的,解決順序隊列的數據搬運問題。
5.7 優先隊列Priority Queue
插入和刪除:O(1)
取出操做:O(logn),按照優先級
底層實現能夠多樣:heap、bst、treap
java中實現:PriorityQueue
5.8 阻塞隊列和併發隊列(CAS)
6.哈希表Hash table(散列表):經過哈希函數(散列函數)映射值。
6.1 模型:Hash函數獲得數組下標 -> 數組(鏈表做爲數組的元素)
插入和刪除:O(1)
查詢:O(1)
說明:可能後面鏈表查詢的複雜度不爲1,可是通常hashCode一致的比較少,
因此鏈表的元素個數其實頗有限,能夠認爲就是O(1)。
6.2 哈希函數
(1)除後取餘數法
(2)平方取中
6.3 java 7中的HashMap是數組和鏈表的結合體。JAVA 8中是數組 + 紅黑樹實現。
(1)對象的HashCode是用來在散列存儲結構中肯定對象的存儲地址的。
(2)若是兩個對象的HashCode相同,即在數組中的地址相同。而數組的元素是鏈表。這兩個對象會放在同一鏈表上。
(3)如何肯定是同一個對象? 經過equals方法。
(4)HashMap默認的加載因子是0.75,默認最大容量是16。
所以能夠得出HashMap的默認實際容量是:0.75*16=12,到了12就會擴容。
擴容大小:擴容原來的一倍。
還有經常使用的 HashMap HashSet。
7. 應用:算術表達式的表示方法
中序法(操做數1-運算符-操做數2): 2*3 + 4*5
中序表達法符合人的習慣,不過計算機處理不方便
前序法(運算符-操做數1-操做數2): +*23*45
經常使用的計算機處理方式
後序法(操做數1-操做數2-運算符): 23*45*+
經常使用的計算機處理方式(比前序經常使用)
7.1 利用堆棧實現表達式運算:最簡單的是後續表達式求值-只須要一個棧。
7.2 可使用二叉樹的方法
7.3 中序轉前序/後序
2*3 + 4*5
(1)括號法: 先括號括起來((2*3) + (4*5))
中序轉前序
用括號內的運算符替代左括號,近者優先:+*23)*45))
去掉全部右括號:+*23*45
中序轉後序
用括號內的運算符替代右括號,近者優先:((23* (45*+
去掉全部左括號:23*45*+
(2)堆棧法
7.4 前序或後序轉中序
(1)括號法
(2)堆棧法