You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript实现MinHeap堆排序输出异常,求代码问题排查

基于MinHeap实现堆排序的问题排查

问题描述

尝试用JavaScript基于MinHeap实现堆排序,但输出结果不正确,数据集包含1000个数字,以下是实现代码:

import * as fs from 'fs';

// Read the input file
const input = fs.readFileSync('data.txt', 'utf8');
let data = input.split(" ").map(Number);

// Call the main function to build the min-heap and print the results
main(data);

// Min-heapify function
function heapify(data, i, n) {
    let left = 2 * i;
    let right = 2 * i + 1;
    let smallest = i;

    if (right <= n && left <= n && data[right] < data[left]) {
        if (data[right] < data[i]) {
            smallest = right;
        }
    }
    else (right <= n && left <= n && data[right] > data[left])
    {
        if (data[left] < data[i]) {
            smallest = left;
        }
    }
    //if smallest is changed to original left or right
    if (smallest != i) {
        // Swap data[i] and data[smallest]
        [data[i], data[smallest]] = [data[smallest], data[i]];

        //Recursively heapify the subtree
        heapify(data, smallest, n);
    }
    return data;
}

// Build min-heap function
function buildMinHeap(data) {
    const n = data.length - 1;
    for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
        heapify(data, i, n);
    }
}

// Main function
function main(data) {

    // Build a min-heap
    buildMinHeap(data);

    // Print the first 20 values data[1], data[2], ..., data[20]
    console.log("First 20 values:");
    const n = data.length;
    for (let i = 0; i <= 19 && i <= n; i++) {
        process.stdout.write(data[i] + ',');
    }

    console.log("Last 20 values:");
    for (let i = n - 1; i >= n - 20 && i >= 1; i--) {
        process.stdout.write(data[i] + ',');
    }
}

问题排查与修正

1. 堆索引逻辑错误

堆的索引计算混淆了1-based和0-based规则:

  • 原代码中left = 2 * i、right = 2 * i + 1是1索引的计算方式,但JavaScript数组采用0索引,正确的子节点索引应为:
    let left = 2 * i + 1;
    let right = 2 * i + 2;
    
  • buildMinHeap中循环起始值错误,正确的非叶子节点起始索引应为Math.floor(data.length / 2) - 1,无需额外对n做减1处理。

2. Heapify函数条件判断漏洞

  • else后不能直接跟条件,应改为else if;且原逻辑未覆盖仅左孩子存在或仅右孩子存在的场景。正确的判断逻辑应先找出左、右孩子中的最小值,再与当前节点比较:
    // 比较左孩子与当前最小值
    if (left <= n && data[left] < data[smallest]) {
        smallest = left;
    }
    // 比较右孩子与当前最小值
    if (right <= n && data[right] < data[smallest]) {
        smallest = right;
    }
    

3. BuildMinHeap循环范围错误

原代码中n = data.length - 1后,循环起始值Math.floor(n / 2) - 1会导致跳过部分非叶子节点,正确的循环范围应为从最后一个非叶子节点开始遍历到根节点:

function buildMinHeap(data) {
    const n = data.length - 1;
    // 从最后一个非叶子节点开始堆化
    for (let i = Math.floor(data.length / 2) - 1; i >= 0; i--) {
        heapify(data, i, n);
    }
}

4. 输出逻辑修正

原代码打印的是data[0]到data[19],但注释说明要打印data[1]到data[20],需调整循环起始值:

// 打印data[1]到data[20]
for (let i = 1; i <= 20 && i < data.length; i++) {
    process.stdout.write(data[i] + ',');
}

完整修正代码

import * as fs from 'fs';

// Read the input file
const input = fs.readFileSync('data.txt', 'utf8');
let data = input.split(" ").map(Number);

// Call the main function to build the min-heap and print the results
main(data);

// Min-heapify function
function heapify(data, i, n) {
    let left = 2 * i + 1;
    let right = 2 * i + 2;
    let smallest = i;

    // 比较左孩子与当前最小值
    if (left <= n && data[left] < data[smallest]) {
        smallest = left;
    }
    // 比较右孩子与当前最小值
    if (right <= n && data[right] < data[smallest]) {
        smallest = right;
    }

    if (smallest !== i) {
        [data[i], data[smallest]] = [data[smallest], data[i]];
        heapify(data, smallest, n);
    }
    return data;
}

// Build min-heap function
function buildMinHeap(data) {
    const n = data.length - 1;
    // 从最后一个非叶子节点开始堆化
    for (let i = Math.floor(data.length / 2) - 1; i >= 0; i--) {
        heapify(data, i, n);
    }
}

// Main function
function main(data) {
    buildMinHeap(data);

    // Print the first 20 values data[1], data[2], ..., data[20]
    console.log("First 20 values:");
    const len = data.length;
    for (let i = 1; i <= 20 && i < len; i++) {
        process.stdout.write(data[i] + ',');
    }
    console.log('\n');

    console.log("Last 20 values:");
    for (let i = len - 1; i >= len - 20 && i >= 1; i--) {
        process.stdout.write(data[i] + ',');
    }
}

内容的提问来源于stack exchange,提问作者Coco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:13:16