从零基础到精通 | 包含常见数据结构、经典算法和复杂度分析
数据结构和算法是编程的基础和灵魂。它们直接影响代码的性能、可维护性和可扩展性。
// O(1) - 常数时间
function getFirst(arr) {
return arr[0];
}
// O(n) - 线性时间
function findMax(arr) {
let max = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] > max) max = arr[i];
}
return max;
}
// O(n²) - 平方时间
function bubbleSort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
}
// O(log n) - 对数时间
function binarySearch(arr, target) {
let left = 0, right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) return mid;
if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}
// O(n log n) - 线性对数时间
function mergeSort(arr) {
if (arr.length <= 1) return arr;
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}// 数组操作
const arr = [1, 2, 3, 4, 5];
// 访问:O(1)
console.log(arr[0]);
// 搜索:O(n)
arr.indexOf(3);
// 插入:O(n)
arr.splice(2, 0, 2.5);
// 删除:O(n)
arr.splice(2, 1);
// 数组的优点:快速随机访问
// 数组的缺点:插入和删除慢// 链表节点
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
// 链表
class LinkedList {
constructor() {
this.head = null;
}
// 插入:O(1)
insertAtHead(value) {
const node = new Node(value);
node.next = this.head;
this.head = node;
}
// 搜索:O(n)
search(value) {
let current = this.head;
while (current) {
if (current.value === value) return true;
current = current.next;
}
return false;
}
// 删除:O(n)
delete(value) {
if (!this.head) return;
if (this.head.value === value) {
this.head = this.head.next;
return;
}
let current = this.head;
while (current.next) {
if (current.next.value === value) {
current.next = current.next.next;
return;
}
current = current.next;
}
}
}
// 链表的优点:快速插入和删除
// 链表的缺点:随机访问慢// 栈实现
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
return this.items.pop();
}
peek() {
return this.items[this.items.length - 1];
}
isEmpty() {
return this.items.length === 0;
}
}
// 应用:括号匹配、表达式求值、回溯
function isValidParentheses(s) {
const stack = new Stack();
const pairs = { ')': '(', '}': '{', ']': '[' };
for (const char of s) {
if (char === '(' || char === '{' || char === '[') {
stack.push(char);
} else {
if (stack.isEmpty() || stack.pop() !== pairs[char]) {
return false;
}
}
}
return stack.isEmpty();
}// 队列实现
class Queue {
constructor() {
this.items = [];
}
enqueue(element) {
this.items.push(element);
}
dequeue() {
return this.items.shift();
}
front() {
return this.items[0];
}
isEmpty() {
return this.items.length === 0;
}
}
// 应用:BFS、任务队列、消息队列
function bfs(graph, start) {
const visited = new Set();
const queue = new Queue();
queue.enqueue(start);
visited.add(start);
while (!queue.isEmpty()) {
const node = queue.dequeue();
console.log(node);
for (const neighbor of graph[node]) {
if (!visited.has(neighbor)) {
queue.enqueue(neighbor);
visited.add(neighbor);
}
}
}
}// 二叉树节点
class TreeNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}
// 二叉搜索树
class BST {
constructor() {
this.root = null;
}
insert(value) {
const node = new TreeNode(value);
if (!this.root) {
this.root = node;
return;
}
let current = this.root;
while (true) {
if (value < current.value) {
if (!current.left) {
current.left = node;
return;
}
current = current.left;
} else {
if (!current.right) {
current.right = node;
return;
}
current = current.right;
}
}
}
search(value) {
let current = this.root;
while (current) {
if (value === current.value) return true;
if (value < current.value) current = current.left;
else current = current.right;
}
return false;
}
}// 前序遍历(根-左-右)
function preorder(node) {
if (!node) return;
console.log(node.value);
preorder(node.left);
preorder(node.right);
}
// 中序遍历(左-根-右)
function inorder(node) {
if (!node) return;
inorder(node.left);
console.log(node.value);
inorder(node.right);
}
// 后序遍历(左-右-根)
function postorder(node) {
if (!node) return;
postorder(node.left);
postorder(node.right);
console.log(node.value);
}
// 层序遍历(BFS)
function levelOrder(root) {
if (!root) return;
const queue = [root];
while (queue.length) {
const node = queue.shift();
console.log(node.value);
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
}// 邻接表表示
const graph = {
'A': ['B', 'C'],
'B': ['A', 'D'],
'C': ['A', 'D'],
'D': ['B', 'C', 'E'],
'E': ['D']
};
// 邻接矩阵表示
const matrix = [
[0, 1, 1, 0, 0],
[1, 0, 0, 1, 0],
[1, 0, 0, 1, 0],
[0, 1, 1, 0, 1],
[0, 0, 0, 1, 0]
];
// DFS(深度优先搜索)
function dfs(graph, node, visited = new Set()) {
visited.add(node);
console.log(node);
for (const neighbor of graph[node]) {
if (!visited.has(neighbor)) {
dfs(graph, neighbor, visited);
}
}
}
// BFS(广度优先搜索)
function bfs(graph, start) {
const visited = new Set([start]);
const queue = [start];
while (queue.length) {
const node = queue.shift();
console.log(node);
for (const neighbor of graph[node]) {
if (!visited.has(neighbor)) {
visited.add(neighbor);
queue.push(neighbor);
}
}
}
}function bubbleSort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}function quickSort(arr) {
if (arr.length <= 1) return arr;
const pivot = arr[0];
const left = arr.slice(1).filter(x => x < pivot);
const right = arr.slice(1).filter(x => x >= pivot);
return [...quickSort(left), pivot, ...quickSort(right)];
}function mergeSort(arr) {
if (arr.length <= 1) return arr;
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}
function merge(left, right) {
const result = [];
let i = 0, j = 0;
while (i < left.length && j < right.length) {
if (left[i] < right[j]) {
result.push(left[i++]);
} else {
result.push(right[j++]);
}
}
return result.concat(left.slice(i), right.slice(j));
}function linearSearch(arr, target) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] === target) return i;
}
return -1;
}function binarySearch(arr, target) {
let left = 0, right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) return mid;
if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}function dfs(node, target, visited = new Set()) {
if (node === target) return true;
visited.add(node);
for (const neighbor of node.neighbors) {
if (!visited.has(neighbor)) {
if (dfs(neighbor, target, visited)) return true;
}
}
return false;
}function bfs(start, target) {
const visited = new Set([start]);
const queue = [start];
while (queue.length) {
const node = queue.shift();
if (node === target) return true;
for (const neighbor of node.neighbors) {
if (!visited.has(neighbor)) {
visited.add(neighbor);
queue.push(neighbor);
}
}
}
return false;
}// 递归(低效)- O(2^n)
function fib(n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
// 动态规划(高效)- O(n)
function fibDP(n) {
if (n <= 1) return n;
const dp = [0, 1];
for (let i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
// 空间优化 - O(1)
function fibOptimized(n) {
if (n <= 1) return n;
let prev = 0, curr = 1;
for (let i = 2; i <= n; i++) {
[prev, curr] = [curr, prev + curr];
}
return curr;
}// 0/1背包问题
function knapsack(weights, values, capacity) {
const n = weights.length;
const dp = Array(capacity + 1).fill(0);
for (let i = 0; i < n; i++) {
for (let w = capacity; w >= weights[i]; w--) {
dp[w] = Math.max(dp[w], dp[w - weights[i]] + values[i]);
}
}
return dp[capacity];
}数据结构和算法需要大量练习。坚持每天做题,逐步提升。
现在你已经掌握了编程的基础知识。
算法是编程的灵魂。投入时间学习,会终身受益。