前端算法:堆

目录

一、堆

1.堆是什么?

2.堆的性质

3.堆的实现

4.基本操作

5.时间复杂度

 二、代码实现

1.最大堆实现

2.最小堆实现


一、堆

1.堆是什么?

堆能用树来表示,并且一般树的实现都是通过链表,而二叉堆是一种特殊的堆,它用完全二叉树来表示,却可以利用数组来实现。

平时使用最多的是二叉堆,它可以用完全二叉树俩表示,二叉堆易于存储,并且便于索引。

注意:堆的数据结构像树,但是通过数组实现、

2.堆的性质

  • 最大堆:每个节点的值都大于或等于其子节点的值,根节点是最大值。
  • 最小堆:每个节点的值都小于或等于其子节点的值,根节点是最小值。

3.堆的实现

  1. 通常使用数组实现。对于任意节点在索引 i
    • 父节点的索引为 (i - 1) / 2
    • 右子节点的索引为 2*i + 2
    • 左子节点的索引为 2*i + 1

4.基本操作

  • 插入:将新元素添加到数组末尾,随后进行“上浮”操作,保持堆的性质。
  • 删除(通常是删除根节点):将根节点与最后一个节点交换,移除最后节点,随后进行“下沉”操作,恢复堆的性质。

5.时间复杂度

插入和删除操作的时间复杂度为 O(log n),而查找最大/最小值的时间复杂度为 O(1)。

 二、代码实现

1.最大堆实现

class MaxHeap {
    constructor() {
        this.heap = [];
    }

    // 插入元素
    insert(value) {
        this.heap.push(value);
        this.bubbleUp();
    }

    // 向上调整
    bubbleUp() {
        let index = this.heap.length - 1;
        while (index > 0) {
            const parentIndex = Math.floor((index - 1) / 2);
            if (this.heap[index] <= this.heap[parentIndex]) break;
            [this.heap[index], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[index]];
            index = parentIndex;
        }
    }

    // 移除最大值
    extractMax() {
        if (this.heap.length === 0) return null;
        if (this.heap.length === 1) return this.heap.pop();
        
        const max = this.heap[0];
        this.heap[0] = this.heap.pop();
        this.bubbleDown();
        return max;
    }

    // 向下调整
    bubbleDown() {
        let index = 0;
        const length = this.heap.length;
        while (true) {
            let leftChildIndex = 2 * index + 1;
            let rightChildIndex = 2 * index + 2;
            let largest = index;

            if (leftChildIndex < length && this.heap[leftChildIndex] > this.heap[largest]) {
                largest = leftChildIndex;
            }
            if (rightChildIndex < length && this.heap[rightChildIndex] > this.heap[largest]) {
                largest = rightChildIndex;
            }
            if (largest === index) break;

            [this.heap[index], this.heap[largest]] = [this.heap[largest], this.heap[index]];
            index = largest;
        }
    }

    // 查看最大值
    peek() {
        return this.heap[0] || null;
    }

    // 获取堆的数组表示
    getHeap() {
        return this.heap;
    }
}

// 使用示例
const maxHeap = new MaxHeap();
maxHeap.insert(10);
maxHeap.insert(20);
maxHeap.insert(5);
console.log(maxHeap.getHeap()); // [ 20, 10, 5 ]
console.log(maxHeap.extractMax()); // 20
console.log(maxHeap.getHeap()); // [ 10, 5 ]

2.最小堆实现

class MinHeap {
    constructor() {
        this.heap = [];
    }

    // 插入元素
    insert(value) {
        this.heap.push(value);
        this.bubbleUp();
    }

    // 向上调整
    bubbleUp() {
        let index = this.heap.length - 1;
        while (index > 0) {
            const parentIndex = Math.floor((index - 1) / 2);
            if (this.heap[index] >= this.heap[parentIndex]) break;
            [this.heap[index], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[index]];
            index = parentIndex;
        }
    }

    // 移除最小值
    extractMin() {
        if (this.heap.length === 0) return null;
        if (this.heap.length === 1) return this.heap.pop();
        
        const min = this.heap[0];
        this.heap[0] = this.heap.pop();
        this.bubbleDown();
        return min;
    }

    // 向下调整
    bubbleDown() {
        let index = 0;
        const length = this.heap.length;
        while (true) {
            let leftChildIndex = 2 * index + 1;
            let rightChildIndex = 2 * index + 2;
            let smallest = index;

            if (leftChildIndex < length && this.heap[leftChildIndex] < this.heap[smallest]) {
                smallest = leftChildIndex;
            }
            if (rightChildIndex < length && this.heap[rightChildIndex] < this.heap[smallest]) {
                smallest = rightChildIndex;
            }
            if (smallest === index) break;

            [this.heap[index], this.heap[smallest]] = [this.heap[smallest], this.heap[index]];
            index = smallest;
        }
    }

    // 查看最小值
    peek() {
        return this.heap[0] || null;
    }

    // 获取堆的数组表示
    getHeap() {
        return this.heap;
    }
}

// 使用示例
const minHeap = new MinHeap();
minHeap.insert(10);
minHeap.insert(20);
minHeap.insert(5);
console.log(minHeap.getHeap()); // [ 5, 10, 20 ]
console.log(minHeap.extractMin()); // 5
console.log(minHeap.getHeap()); // [ 10, 20 ]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值