JS (node) 监听输入输出的方法

对之前这篇文章《JS (node) 的 ACM 模式 + debug方法 (01背包为例)》 做一点补充。

事件监听方式

使用 readline.on('line', callback) 逐行监听输入,将每一行存储到 input 数组中。然后再对提取出 input 中的参数做题。

需要在 readline.close() 后,手动处理输入的数据。

适用于需要一次性读取所有数据,然后再处理的场景。

const readline = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

readline.on('line', (line) => {
    input.push(line);
});

readline.on('close', () => {
    // 读取输入并初始化图
    const [N, M] = input[0].split(' ').map(Number);
    const graph = Array.from({ length: N + 1 }, () => Array(N + 1).fill(0));

    for (let i = 1; i <= M; i++) {
        const [s, t] = input[i].split(' ').map(Number);
        graph[s][t] = 1;
    }

    let result = [];
    let path = [1];

    function dfs(node) {
        if (node === N) {
            result.push([...path]);
            return;
        }
        for (let next = 1; next <= N; next++) {
            if (graph[node][next] === 1) {
                path.push(next);
                dfs(next);
                path.pop();
            }
        }
    }

    dfs(1);

    if (result.length > 0) {
        result.forEach(p => console.log(p.join(' ')));
    } else {
        console.log(-1);
    }
});

Symbol.asyncIterator 的方式

使用异步迭代器逐行读取输入,每次调用 await iter.next() 以获取新行。

数据读取和处理可以同时进行,直接在读取过程中执行逻辑。

更加灵活,适合逐行处理输入数据,尤其是在输入数据量较大时,可以减少内存消耗。

const readline = require('readline').createInterface({ input: process.stdin });
let iter = readline[Symbol.asyncIterator]();

// 异步读取一行输入
const getLine = async () => (await iter.next()).value;

let graph; // 邻接矩阵
let N, M; // 节点数和边数
let result = []; // 保存所有路径
let path = []; // 当前路径

// 初始化邻接矩阵
async function initGraph() {
    const firstLine = await getLine();
    [N, M] = firstLine.split(' ').map(Number);
    
    // 创建一个 (N+1) x (N+1) 的矩阵,初始化为 0
    graph = Array.from({ length: N + 1 }, () => Array(N + 1).fill(0));
    
    // 读取边并填充邻接矩阵
    for (let i = 0; i < M; i++) {
        const edge = await getLine();
        const [s, t] = edge.split(' ').map(Number);
        graph[s][t] = 1; // 表示从 s 到 t 有边
    }
}

// 深度优先搜索
function dfs(node) {
    if (node === N) {
        result.push([...path]); // 找到一条路径,保存结果
        return;
    }
    for (let next = 1; next <= N; next++) {
        if (graph[node][next] === 1) { // 如果有边
            path.push(next); // 添加到路径
            dfs(next); // 递归搜索下一个节点
            path.pop(); // 回溯
        }
    }
}

(async function () {
    // 初始化图
    await initGraph();

    // 从节点 1 开始搜索
    path.push(1);
    dfs(1);

    // 输出结果
    if (result.length > 0) {
        result.forEach(p => console.log(p.join(' ')));
    } else {
        console.log(-1); // 如果没有路径
    }

    readline.close();
})();

补充 readline

通过 readline 读取的 input 中的每一行默认都是字符串类型。无论输入的是数字、字母还是其他字符,最终都会以 字符串 的形式存储在 input 中。

const readline = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

readline.on('line', (line) => {
    input.push(line);
});

readline.on('close', () => {
    console.log(input); // 打印 input 的内容
});

如果输入

5 5
1 3
3 5
1 2
2 4
4 5

那么输出

[
  '5 5',
  '1 3',
  '3 5',
  '1 2',
  '2 4',
  '4 5'
]

如果需要将字符串解析成数字或其他类型,需要手动转换。例如:

const [a, b] = '5 5'.split(' ').map(Number); 
// 转换为数字数组 [5, 5]

input.split(' ') 将字符串 "5 10" 按空格分割成数组:['5', '10'].map(Number) 将数组中的每个字符串转换为数字:[5, 10][a, b] 解构数组,将 5 赋值给 a,10 赋值给 b。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值