一、數組(Array)
定義:連續存儲相同類型數據的線性結構,支持隨機訪問。
應用場景:列表渲染、數據緩存、算法處理
代碼示例:
// 數組基本操作
const arr = [1, 2, 3, 4];
arr.push(5); // O(1) 平均時間復雜度
arr.pop(); // O(1)
arr.shift();// O(n) 不推薦高頻使用
arr.unshift(0); // O(n)// 數組遍歷優化
// 推薦寫法(減少屬性查找)
for (let i = 0, len = arr.length; i < len; i++) {console.log(arr[i]);
}// 二維數組初始化
const matrix = Array.from({ length: 3 }, () => new Array(3).fill(0));
使用建議:
- 優先使用?
push/pop
?替代?shift/unshift
- 大數據量時避免頻繁操作數組頭部
- 遍歷數組使用?
for
?循環而非?forEach
?可提高性能 - 多維數組建議使用?
Array.from
?初始化
注意事項:
- 警惕數組越界訪問
- 避免使用稀疏數組(會影響性能)
- 注意數組原型鏈方法的副作用(如?
sort
?會改變原數組)
二、鏈表(Linked List)
定義:由節點組成的鏈式結構,節點包含值和指向下一個節點的指針
應用場景:內存管理、DOM 節點操作、LRU 緩存
代碼示例:
class ListNode {constructor(val, next) {this.val = (val === undefined ? 0 : val);this.next = (next === undefined ? null : next);}
}// 鏈表反轉
function reverseList(head) {let prev = null;let current = head;while (current) {const next = current.next;current.next = prev;prev = current;current = next;}return prev;
}
使用建議:
- 插入 / 刪除操作優先使用鏈表
- 實現雙向鏈表時維護好前驅指針
- 使用虛擬頭節點簡化邊界條件處理
注意事項:
- 避免循環引用導致內存泄漏
- 注意空指針檢查
- 遍歷鏈表時設置終止條件
- 內存分配比數組更碎片化
三、棧(Stack)
定義:遵循后進先出(LIFO)原則的線性結構
應用場景:路由管理、撤銷重做、函數調用棧
代碼示例:
class Stack {constructor() {this.items = [];}push(element) {this.items.push(element);}pop() {return this.items.pop();}peek() {return this.items[this.items.length - 1];}
}// 瀏覽器路由棧模擬
const routerStack = new Stack();
routerStack.push('/home');
routerStack.push('/about');
routerStack.pop(); // 返回 '/about',當前棧頂 '/home'
使用建議:
- 用數組實現簡單棧時,直接使用?
push/pop
- 需要高性能時考慮使用?
Uint8Array
?實現 - 限制棧的最大深度防止溢出
注意事項:
- 處理棧溢出(Stack Overflow)
- 避免在棧中存儲過大對象
- 遞歸深度受限于棧大小
四、隊列(Queue)
定義:遵循先進先出(FIFO)原則的線性結構
應用場景:任務調度、事件隊列、消息緩沖
代碼示例:
class Queue {constructor() {this.items = [];}enqueue(element) {this.items.push(element);}dequeue() {return this.items.shift();}front() {return this.items[0];}
}// 任務隊列處理
const taskQueue = new Queue();
taskQueue.enqueue(() => console.log('Task 1'));
taskQueue.enqueue(() => console.log('Task 2'));
taskQueue.dequeue()(); // 執行 Task 1
使用建議:
- 優先使用?
enqueue
?+?pop
?替代?shift
- 使用雙端隊列(Deque)實現更靈活操作
- 限制隊列長度防止內存耗盡
注意事項:
- 避免饑餓問題(高優先級任務阻塞隊列)
- 處理并發訪問時需加鎖
- 內存泄漏風險(未及時釋放舊任務)
五、哈希表(Hash Table)
定義:通過哈希函數將鍵映射到存儲位置的結構
應用場景:狀態管理、緩存、快速查找
代碼示例:
class HashTable {constructor(size = 1024) {this.table = new Array(size);this.size = size;}hash(key) {let hash = 0;for (let i = 0; i < key.length; i++) {hash += key.charCodeAt(i);}return hash % this.size;}set(key, value) {const index = this.hash(key);this.table[index] = value;}get(key) {const index = this.hash(key);return this.table[index];}
}// 簡單狀態管理
const state = new HashTable();
state.set('user', { name: 'John', age: 30 });
console.log(state.get('user'));
使用建議:
- 選擇合適的哈希函數(如 BKDRHash)
- 負載因子控制在 0.75 以下
- 實現沖突解決(開放尋址法 / 鏈地址法)
注意事項:
- 哈希沖突的處理
- 鍵的可哈希性(對象需重寫 toString)
- 動態擴容的性能消耗
六、樹(Tree)
定義:n 個節點構成的有限集合,具有層次關系
應用場景:DOM 樹、路由配置、算法優化
代碼示例:
class TreeNode {constructor(val) {this.val = val;this.left = null;this.right = null;}
}// 二叉樹前序遍歷
function preorderTraversal(root) {const result = [];function traverse(node) {if (!node) return;result.push(node.val);traverse(node.left);traverse(node.right);}traverse(root);return result;
}// 構建DOM樹
const div = document.createElement('div');
const span = document.createElement('span');
div.appendChild(span);
使用建議:
- 使用遞歸實現樹遍歷需注意棧溢出
- 優先使用迭代法(如 Morris 遍歷)優化空間復雜度
- 樹的深度控制在合理范圍
注意事項:
- 樹的平衡問題(AVL 樹 / RBTree)
- 內存泄漏(未釋放子節點引用)
- 遍歷順序的選擇(前序 / 中序 / 后序)
七、圖(Graph)
定義:由節點和邊構成的非線性結構
應用場景:社交網絡、路徑規劃、依賴分析
代碼示例:
class Graph {constructor() {this.adjList = new Map();}addVertex(vertex) {if (!this.adjList.has(vertex)) {this.adjList.set(vertex, new Set());}}addEdge(v1, v2) {if (this.adjList.has(v1) && this.adjList.has(v2)) {this.adjList.get(v1).add(v2);this.adjList.get(v2).add(v1);}}bfs(start) {const visited = new Set();const queue = [start];visited.add(start);while (queue.length) {const node = queue.shift();console.log(node);this.adjList.get(node).forEach(neighbor => {if (!visited.has(neighbor)) {visited.add(neighbor);queue.push(neighbor);}});}}
}// 頁面依賴關系圖
const graph = new Graph();
graph.addVertex('A');
graph.addVertex('B');
graph.addEdge('A', 'B');
graph.bfs('A'); // 輸出 A -> B
使用建議:
- 選擇鄰接表存儲稀疏圖
- 使用鄰接矩陣存儲稠密圖
- 路徑查找使用 Dijkstra/A * 算法
注意事項:
- 圖的遍歷需要標記訪問狀態
- 處理環的問題(強連通分量)
- 內存消耗較大,需注意優化
總結建議
- 空間與時間權衡:根據數據量和操作類型選擇結構
- 性能優化:避免在高頻操作中使用低效率方法
- 內存管理:及時釋放不再使用的結構引用
- 算法適配:不同場景選擇對應算法(如樹用 DFS,圖用 BFS)
- 邊界處理:空值檢查、越界處理等防御性編程
建議在實際開發中建立數據結構選擇決策表,根據具體場景評估時間復雜度、空間復雜度和操作頻率,同時結合瀏覽器 / Node.js 環境特性進行優化。