/**
* quick-find 算法, find 操作速度很快, find 只需要返回 id[X],
* 但它无法处理大型问题, 因为它在每一次 union 时都要扫描整个数组
*/
const inquirer = require("inquirer");
class UF{
constructor(N) {
// count 代表分量数量
let count = N;
// id 代表分量id, 以触点作为索引;
// 这样创建的数组内容全空, 不能使用 map
let id = new Array(N);
for (let i = 0; i < N; i++) {
id[i] = i;
}
this.getId = ()=>id;
// 方法区
// 获取私有变量, 连通分量的数量
this.getCount = ()=> count;
// 如果 p 和 q 存在于同一个分量中则返回 true
this.connected = (p,q ) => this.find(p) === this.find(q);
// 找到 p 所在的分量的标识符
// quick-find 算法
this.find = p => id[p];
// 在 p 和 q 之间添加一条连接
this.union = (p, q) => {
const pID = this.find(p);
const qID = this.find(q);
if(pID === qID) return;
id = id.map(value => {
if (value === pID){
return qID;
}else {
return value;
}
})
count--;
}
}
}
const uf = new UF(10);
// 安装 npm install inquirer, 提供了很好的从命令行接收输入的解决方案
const question1 = {
type: 'number',
name: 'count',
message: "触点有多少个?
"
}
const question2 = {
type: 'input',
name: 'points',
filter(input){
return input.split(' ').map(value => Number(value))
},
}
// 输入触手个数
const prompt1 = inquirer.createPromptModule();
// 连接位置
const prompt2 = inquirer.createPromptModule();
prompt1(question1)
.then(answers => {
console.log(`触点有${answers.count}个`)
autoInput();
})
.catch(e =>{
console.error(e)
});
// 输入连接位置
function autoInput(){
prompt2(question2)
.then(answers =>{
console.log(answers)
if(answers.points.length !== 1){
let p = answers.points[0];
let q = answers.points[1];
console.log(p, q)
if(!uf.connected(p, q)) {
uf.union(p, q);
}
autoInput();
}else {
console.log(uf.getId(), 'id')
console.log(uf.getCount(), '基数');
console.log(uf.connected(5, 0), '5和0 是否连接')
console.log(uf.connected(5, 2), '5和2 是否连接')
}
})
.catch(e => {
console.log(e);
})
}