面经四:js的数据结构

78 阅读3分钟

在 JavaScript 中,虽然不像传统的编程语言(如 Java 或 Python)有丰富的内置数据结构,但我们可以利用 JavaScript 的语言特性实现多种数据结构。以下是一些常见的数据结构及其在 JavaScript 中的实现方式:


1. 数组(Array)

数组是 JavaScript 中最常用的数据结构之一,用于存储有序的元素集合。

特点:

  • 动态大小:可以动态地添加或删除元素。
  • 索引访问:通过索引快速访问元素。
  • 方法丰富:提供了大量的内置方法(如 pushpopshiftunshiftslicesplicemapfilter 等)。

示例:

let arr = [1, 2, 3];
arr.push(4); // 添加元素
console.log(arr.pop()); // 删除最后一个元素并返回
console.log(arr[0]); // 通过索引访问

2. 对象(Object)

对象是 JavaScript 中的核心数据结构,用于存储键值对(key-value pairs)。

特点:

  • 无序集合:对象的键是无序的。
  • 动态属性:可以动态地添加或删除属性。
  • 灵活的键类型:键可以是字符串或 Symbol。

示例:

let person = {
    name: "Alice",
    age: 25,
    greet: function() {
        console.log(`Hello, my name is ${this.name}`);
    }
};

person.greet(); // 调用方法
person.email = "alice@example.com"; // 添加属性
delete person.age; // 删除属性

3. 集合(Set)

ES6 引入了 Set 数据结构,用于存储唯一的值。

特点:

  • 唯一性:集合中的值是唯一的,不允许重复。
  • 动态大小:可以动态地添加或删除元素。
  • 方法丰富:提供了 adddeletehasclear 等方法。

示例:

let set = new Set();
set.add(1);
set.add(2);
set.add(2); // 重复值不会被添加
console.log(set.has(2)); // true
console.log(set.size); // 2
set.delete(1);
console.log(set.size); // 1

4. 映射(Map)

ES6 引入了 Map 数据结构,用于存储键值对。

特点:

  • 键值对:键和值可以是任意类型。
  • 动态大小:可以动态地添加或删除键值对。
  • 方法丰富:提供了 setgethasdeleteclear 等方法。

示例:

let map = new Map();
map.set("name", "Alice");
map.set("age", 25);
console.log(map.get("name")); // Alice
console.log(map.has("age")); // true
map.delete("age");
console.log(map.size); // 1

5. 队列(Queue)

队列是一种先进先出(FIFO)的数据结构。虽然 JavaScript 没有内置的队列类型,但可以通过数组实现。

实现:

class Queue {
    constructor() {
        this.items = [];
    }

    enqueue(item) {
        this.items.push(item);
    }

    dequeue() {
        if (this.isEmpty()) return null;
        return this.items.shift();
    }

    isEmpty() {
        return this.items.length === 0;
    }

    peek() {
        if (this.isEmpty()) return null;
        return this.items[0];
    }
}

let queue = new Queue();
queue.enqueue(1);
queue.enqueue(2);
console.log(queue.dequeue()); // 1
console.log(queue.peek()); // 2

6. 栈(Stack)

栈是一种后进先出(LIFO)的数据结构。可以通过数组实现。

实现:

class Stack {
    constructor() {
        this.items = [];
    }

    push(item) {
        this.items.push(item);
    }

    pop() {
        if (this.isEmpty()) return null;
        return this.items.pop();
    }

    isEmpty() {
        return this.items.length === 0;
    }

    peek() {
        if (this.isEmpty()) return null;
        return this.items[this.items.length - 1];
    }
}

let stack = new Stack();
stack.push(1);
stack.push(2);
console.log(stack.pop()); // 2
console.log(stack.peek()); // 1

7. 链表(LinkedList)

链表是一种线性数据结构,每个节点包含数据和指向下一个节点的指针。

实现:

class Node {
    constructor(data) {
        this.data = data;
        this.next = null;
    }
}

class LinkedList {
    constructor() {
        this.head = null;
    }

    append(data) {
        let newNode = new Node(data);
        if (!this.head) {
            this.head = newNode;
            return;
        }
        let current = this.head;
        while (current.next) {
            current = current.next;
        }
        current.next = newNode;
    }

    print() {
        let current = this.head;
        while (current) {
            console.log(current.data);
            current = current.next;
        }
    }
}

let list = new LinkedList();
list.append(1);
list.append(2);
list.print(); // 输出 1, 2

8. 树(Tree)

树是一种层次化的数据结构,包含节点和边。二叉树是树的一种常见形式。

实现:

class TreeNode {
    constructor(value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }
}

class BinaryTree {
    constructor() {
        this.root = null;
    }

    insert(value) {
        let newNode = new TreeNode(value);
        if (!this.root) {
            this.root = newNode;
            return;
        }
        let current = this.root;
        while (true) {
            if (value < current.value) {
                if (!current.left) {
                    current.left = newNode;
                    break;
                }
                current = current.left;
            } else {
                if (!current.right) {
                    current.right = newNode;
                    break;
                }
                current = current.right;
            }
        }
    }

    traverseInOrder(node = this.root) {
        if (!node) return;
        this.traverseInOrder(node.left);
        console.log(node.value);
        this.traverseInOrder(node.right);
    }
}

let tree = new BinaryTree();
tree.insert(10);
tree.insert(5);
tree.insert(15);
tree.traverseInOrder(); // 输出 5, 10, 15

9. 哈希表(Hash Table)

哈希表是一种通过哈希函数将键映射到值的数据结构。虽然 JavaScript 中的 MapObject 已经实现了类似的功能,但可以手动实现一个简单的哈希表。

实现:

class HashTable {
    constructor(size = 10) {
        this.buckets = new Array(size);
        this.size = size;
    }

    hash(key) {
        let hash = 0;
        for (let char of key) {
            hash += char.charCodeAt(0);
        }
        return hash % this.size;
    }

    set(key, value) {
        let index = this.hash(key);
        if (!this.buckets[index]) {
            this.buckets[index] = [];
        }
        this.buckets[index].push([key, value]);
    }

    get(key) {
        let index = this.hash(key);
        if (this.buckets[index]) {
            for (let pair of this.buckets[index]) {
                if (pair[0] === key) {
                    return pair[1];
                }
            }
        }
        return null;
    }
}

let hashTable = new HashTable();
hashTable.set("name", "Alice");
console.log(hashTable.get("name")); // Alice

10. 图(Graph)

图是一种由节点和边组成的复杂数据结构,可以用来表示复杂的网络关系。

实现:

class Graph {
    constructor() {
        this.adjacencyList = {};
    }

    addVertex(vertex) {
        if (!this.adjacencyList[vertex]) {
            this.adjacencyList[vertex] = [];
        }
    }

    addEdge(v1, v2) {
        this.adjacencyList[v1].push(v2);
        this.adjacencyList[v2].push(v1);
    }

    print() {
        for (let vertex in this.adjacencyList) {
            console.log(vertex, "->", this.adjacencyList[vertex]);
        }
    }
}

let graph = new Graph();
graph.addVertex("A");
graph.addVertex("B");
graph.addVertex("C");
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.print(); // 输出 A -> [ 'B', 'C' ], B -> [ 'A' ], C -> [ 'A' ]