2.陣列、連結串列、跳錶的基本實現和特性 (7 天掌握演算法面試必考知識點)
全文內容主要源於極客大學的演算法課,僅作為筆記使用。
1、陣列
陣列:在記憶體中,佔用連續記憶體空間的,有序的元素序列。
陣列元素的型別沒有要求,即為泛型。
底層原理
當申請陣列時,記憶體管理器分配一個連續的記憶體地址。每一個地址可以直接通過記憶體管理器進行訪問。
如下圖所示,即為陣列相應的記憶體地址:
直接訪問的話,訪問第一個元素和訪問任意一個元素,時間複雜度都是一樣的,為O(1)。
陣列特性
訪問速度快
訪問陣列時,其實是利用指標,即記憶體地址,直接訪問對應記憶體地址中的數值,所以訪問速度非常快。
訪問陣列的時間複雜度:常數複雜度 O(1)
刪除和插入: O(n)
如下圖所示:
當向陣列中插入元素D時,首先要將E、F、G都向下挪動一個位置,然後將index=3的地址值賦值為D。
同理:
- 最慢的插入操作:插入位置為第一個元素位置,要挪動n個元素,時間複雜度為O(n)
- 最快的插入操作:插入位置為最後一個元素位置,不需要挪動元素,時間複雜度為O(1)
- 平均要挪動一半元素
Array各操作時間複雜度
prepend: O(n),正常情況下是O(n),但是可以進行特殊優化到O(1)。初始化時申請稍大一些的記憶體空間,然後在陣列最開始預留一部分空間,然後prepend操作只需要把頭下標千一一個位置即可。
append: O(1)
lookup: O(1)
insert: O(n)
delete: O(n)
2、連結串列(LinkedList)
概念
連結串列:元素由Value和next組成,next指向下一個元素,在記憶體中是非連續空間。連結串列元素一般由class定義。
單向連結串列:如果只有一個next指標,是單向連結串列。
雙向連結串列:如果由兩個指標,next指向下一個元素,先前指標prev或previous指向上一個元素。一般頭叫做Head,尾叫做Tail。
迴圈連結串列:如果next指向Head,叫做迴圈連結串列。
LinkedList定義
最簡單的連結串列定義:
class LinkedList {
Node head; // head of list
/* Linked List Node */
class Node {
int data;
Node next;
Node(int d) { data = d; }
}
}
插入和刪除
增加節點
節點增加步驟:
- 插入位置前面的node.next指向new node
- new node的next指向插入位置後面的node 由於只有兩步操作,所以時間複雜度為O(1)
刪除節點
刪除節點為增加節點的逆操作。
刪除節點步驟:
- target_node.prev_node.next = target_node.next_node 只有一步操作,時間複雜度為O(1)。
由此可見,連結串列的增加和刪除,沒有引起整個連結串列的群移操作,也不需要複製元素。所以移動或修改連結串列的效率非常高,時間複雜度為O(1)。
但是,正因為連結串列的這種特性,當訪問中間節點時,必須從Head Node一步一步往後找,時間複雜度為O(n)
連結串列各操作時間複雜度
3、跳錶 Skiped List
科學家在陣列和連結串列基礎上,優化了新的資料結構,即 跳錶。
主要關注:升維思想+空間換時間
跳錶的特點
注意:只能用於元素有序的情況。
所以,跳錶對標的是平衡樹(VAL Tree)和二分查詢,是一種插入/刪除/查詢 都是O(log n)的資料結構。
它最大的優勢是原理簡單、容易實現、方便擴充套件、效率更高。因此在一些熱門的專案裡用於替代平衡樹,如Redis、LevelDB等。
如何給有序的連結串列加速
有序一維資料結構加速理念:經常採用的方式就是升維,也就是說變成二維。
(1)加一級索引
第一級索引指向的是next.next
(2)加二級索引
二級索引next指向的是一級索引連結串列的next.next
(3)多級索引
以此類推,加多級索引如下圖所示:
跳錶查詢的時間複雜度
n/2、n/4、n/8,第k級索引節點的個數就是n/(2k)
假設索引有h級,最高階的索引有2個結點。n / (2h) = 2,從而求得 h = log2(n) - 1
假設原始連結串列要查詢1024次的話,那麼跳錶的時間複雜度是log2(n),即10次就可以找到元素。
現實中的跳錶
如下圖所示,現實中的跳錶,由於多次的增加和刪除,導致有些索引並不是完全工整的,最後經過多次改動後,有些地方的索引會多跨幾步,有些地方會少跨或只跨兩步。
維護成本相對較高,比如增加或刪除一個元素的話,索引要更新一遍,此時時間複雜度就變為Logn了。
空間複雜度
跳錶的空間複雜度為O(n),但是比原始連結串列要多很多。
4、更多
LRU快取演算法
跳錶在Redis中的使用
跳躍表、為啥 Redis 使用跳錶(Skip List)而不是使用 Red-Black?
相關文章
- 1. 時間複雜度和空間複雜度 (7 天掌握演算法面試必考知識點)時間複雜度演算法面試
- 面試-陣列和連結串列的區別面試陣列
- 資料結構與演算法知識點總結(1)陣列與連結串列資料結構演算法陣列
- 連結串列中的跳錶小結
- 陣列和連結串列陣列
- 跳錶 | 會跳的連結串列真的非常diao
- 歸併排序:陣列和連結串列的多種實現排序陣列
- 面試需要掌握的知識點面試
- 連結串列、棧、佇列、KMP相關知識點佇列KMP
- day1-陣列和連結串列陣列
- 陣列與連結串列陣列
- 資料結構-棧(通過陣列和單向連結串列實現)資料結構陣列
- 資料結構--單連結串列(通過陣列實現)資料結構陣列
- 演算法面試(一) 連結串列演算法面試
- 資料結構-2.單向連結串列的實現資料結構
- 面試 7:快慢指標法玩轉連結串列演算法面試(一)面試指標演算法
- 資料結構和演算法面試題系列—連結串列資料結構演算法面試題
- 【第7期】盤點那些面試中會被問到的連結串列演算法題面試演算法
- 連結串列還會用嗎?用連結串列實現佇列(附演算法原始碼)佇列演算法原始碼
- 用連結串列實現佇列的功能佇列
- 可變陣列——連結串列前言陣列
- 陣列模擬單連結串列陣列
- 玩轉演算法面試之連結串列演算法面試
- CSS知識點面試總結CSS面試
- java面試知識點總結Java面試
- Java 面試知識點總結Java面試
- 資料結構與演算法整理總結---陣列,連結串列資料結構演算法陣列
- 面試總結:Promise有關面試的知識點。面試Promise
- 資料結構--陣列、單向連結串列、雙向連結串列資料結構陣列
- 連結串列-單連結串列實現
- 基本資料結構實現--單連結串列【含測試程式碼】資料結構
- 基本資料結構實現--雙連結串列【含測試程式碼】資料結構
- 95%的技術面試必考的JVM知識點都在這,另附加分思路!面試JVM
- 線性結構 陣列與連結串列陣列
- php實現基本資料結構之連結串列PHP資料結構
- C++連結串列常見面試考點C++面試
- Linux命令有哪些知識點需要掌握?面試題Linux面試題
- Redis知識點&面試題總結Redis面試題