在 JavaScript 里,数据结构和算法是十分关键的部分,下面介绍几种常见的数据结构和对应的算法。
-
数组(Array)
数组是最基础的数据结构,用于存储一系列有序的数据。// 创建数组 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)的数据结构,仅能在栈顶进行插入和删除操作。class 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)的数据结构,元素从队尾入队,从队头出队。class 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)
链表是由节点构成的数据结构,每个节点包含数据和指向下一个节点的指针。class 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)
冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。function 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]
-
二叉树
二叉树是每个节点最多有两个子节点的树结构,这两个子节点通常被称为左子节点和右子节点。// 二叉树节点类 class TreeNode {constructor(value) {// 节点存储的值this.value = value;// 左子节点,初始为 nullthis.left = null;// 右子节点,初始为 nullthis.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);
二叉树是一种灵活且强大的数据结构,不同的遍历方式适用于不同的场景。前序遍历常用于复制二叉树、表达式树求值;中序遍历常用于二叉搜索树的排序输出;后序遍历常用于释放二叉树的节点内存;层序遍历常用于按层次访问节点。