在 JavaScript 里,数据结构和算法是十分关键的部分,下面介绍几种常见的数据结构和对应的算法。
-
数组(Array)
数组是最基础的数据结构,用于存储一系列有序的数据。
javascript// 创建数组 const arr = [1, 2, 3, 4, 5]; // 访问元素 console.log(arr[0]); // 输出 1 // 修改元素 arr[0] = 10; console.log(arr); // 输出 [10, 2, 3, 4, 5] // 遍历数组 for (let i = 0; i < arr.length; i++) { console.log(arr[i]); }
-
栈(Stack)
栈是一种后进先出(LIFO)的数据结构,仅能在栈顶进行插入和删除操作。
javascriptclass Stack { constructor() { this.items = []; } // 入栈 push(element) { this.items.push(element); } // 出栈 pop() { if (this.isEmpty()) { return null; } return this.items.pop(); } // 获取栈顶元素 peek() { if (this.isEmpty()) { return null; } return this.items[this.items.length - 1]; } // 判断栈是否为空 isEmpty() { return this.items.length === 0; } // 获取栈的大小 size() { return this.items.length; } } // 使用栈 const stack = new Stack(); stack.push(1); stack.push(2); console.log(stack.pop()); // 输出 2
-
队列(Queue)
队列是一种先进先出(FIFO)的数据结构,元素从队尾入队,从队头出队。
javascriptclass Queue { constructor() { this.items = []; } // 入队 enqueue(element) { this.items.push(element); } // 出队 dequeue() { if (this.isEmpty()) { return null; } return this.items.shift(); } // 获取队头元素 front() { if (this.isEmpty()) { return null; } return this.items[0]; } // 判断队列是否为空 isEmpty() { return this.items.length === 0; } // 获取队列的大小 size() { return this.items.length; } // 清空队列 clear() { this.items = []; } } // 使用队列 const queue = new Queue(); queue.enqueue(1); queue.enqueue(2); console.log(queue.dequeue()); // 输出 1
-
链表(Linked List)
链表是由节点构成的数据结构,每个节点包含数据和指向下一个节点的指针。
javascriptclass Node { constructor(data) { this.data = data; this.next = null; } } class LinkedList { constructor() { this.head = null; this.length = 0; } // 在链表尾部添加节点 append(data) { const newNode = new Node(data); if (this.head === null) { this.head = newNode; } else { let current = this.head; while (current.next !== null) { current = current.next; } current.next = newNode; } this.length++; } // 打印链表 print() { let current = this.head; const result = []; while (current !== null) { result.push(current.data); current = current.next; } console.log(result.join(' -> ')); } } // 使用链表 const linkedList = new LinkedList(); linkedList.append(1); linkedList.append(2); linkedList.print(); // 输出 1 -> 2
-
排序算法 - 冒泡排序(Bubble Sort)
冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
javascriptfunction bubbleSort(arr) { const len = arr.length; for (let i = 0; i < len - 1; i++) { for (let j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { // 交换元素 [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; } } } return arr; } const unsortedArray = [5, 3, 8, 4, 2]; const sortedArray = bubbleSort(unsortedArray); console.log(sortedArray); // 输出 [2, 3, 4, 5, 8]
-
二叉树
二叉树是每个节点最多有两个子节点的树结构,这两个子节点通常被称为左子节点和右子节点。
javascript// 二叉树节点类 class TreeNode { constructor(value) { // 节点存储的值 this.value = value; // 左子节点,初始为 null this.left = null; // 右子节点,初始为 null this.right = null; } } // 创建根节点 const root = new TreeNode(1); // 为根节点添加左子节点 root.left = new TreeNode(2); // 为根节点添加右子节点 root.right = new TreeNode(3); // 为左子节点添加左子节点 root.left.left = new TreeNode(4); // 为左子节点添加右子节点 root.left.right = new TreeNode(5); // 前序遍历 function preOrderTraversal(node) { if (node === null) { return; } console.log(node.value); preOrderTraversal(node.left); preOrderTraversal(node.right); } // 对上述构建的二叉树进行前序遍历 preOrderTraversal(root); // 中序遍历 function inOrderTraversal(node) { if (node === null) { return; } inOrderTraversal(node.left); console.log(node.value); inOrderTraversal(node.right); } // 对上述构建的二叉树进行中序遍历 inOrderTraversal(root); // 后续遍历 function postOrderTraversal(node) { if (node === null) { return; } postOrderTraversal(node.left); postOrderTraversal(node.right); console.log(node.value); } // 对上述构建的二叉树进行后序遍历 postOrderTraversal(root); // 层序遍历 function levelOrderTraversal(root) { if (root === null) { return; } const queue = [root]; while (queue.length > 0) { const current = queue.shift(); console.log(current.value); if (current.left!== null) { queue.push(current.left); } if (current.right!== null) { queue.push(current.right); } } } // 对上述构建的二叉树进行层序遍历 levelOrderTraversal(root);
二叉树是一种灵活且强大的数据结构,不同的遍历方式适用于不同的场景。前序遍历常用于复制二叉树、表达式树求值;中序遍历常用于二叉搜索树的排序输出;后序遍历常用于释放二叉树的节点内存;层序遍历常用于按层次访问节点。