// 梯子节点检测脚本
function detectLadderNodes() { // 初始化节点数据结构 const nodes = { id: 1, parent: null, children: [], isRemoved: false };
// 创建节点输入界面
function createNode() {
const node = {
id: Date.now(),
parent: null,
children: [],
isRemoved: false
};
nodes[node.id] = node;
// 可选性功能:显示节点信息
document.getElementById('nodeInput').value += 节点${node.id}: ${JSON.stringify(node, null, 2)};
// 可选性功能:节点删除
document.getElementById('nodeInput').value += '节点' + node.id + '被删除了';
return true;
}
// 输入节点和指向关系 function inputNodesAndRelationship() { const nodeInputElement = document.getElementById('nodeInput'); const targetId = prompt('请输入节点ID:', '请按“节点ID”开始输入(1, 2, 3, ...)');
if (targetId) {
const node = nodes[targetId];
node.isRemoved = false;
node.parent = null;
node.children = [];
// 添加节点到树状图中
document.body.appendChild({
'node' : { id: targetId, parent: node.parent, children: node.children },
'tree' : { root: null, children: node.children }
});
// 添加指向关系
const sourceId = prompt('请输入源节点ID:', '请按“源节点ID”开始输入(1, 2, 3, ...)');
if (sourceId) {
const targetNode = nodes[sourceId];
targetNode.parent = targetId;
targetNode.isRemoved = false;
// 添加指向关系
document.body.appendChild({
'node' : { id: sourceId, parent: targetId, children: [] },
'tree' : { root: targetId, children: [] }
});
// 检查是否形成环
if (isLadderGraph(nodes)) {
alert('这是一个有效的梯子节点!节点结构如下:');
// 显示树状图
renderTree(nodes);
} else {
alert('输入的指向关系不正确,请重新输入数据并重复此步骤;');
document.body.removeChild({
'node': {
id: sourceId,
parent: targetId,
children: []
}
});
}
} else {
alert('请输入节点ID:请按“节点ID”开始输入(1, 2, 3, ...)');
}
} else {
alert('输入节点ID时,请按“节点ID”开始输入(1, 2, 3, ...)');
}
// 检查是否为梯子节点(有向无环图) function isLadderGraph(nodes) { const root = -1; const hasCycle = false;
// 遍历所有节点
for (let i = 1; i <= nodes.length; i++) {
const node = nodes[i];
if (node.parent !== null) {
const root = node.parent;
if (root != root) {
return false;
}
}
// 检查是否有环
if (hasCycle) {
return false;
}
// 遍历子节点
const childList = [...nodes.slice(, i).keys()];
for (const child of childList) {
if (child !== node.children[]) {
const nextNode = nodes[child];
if (nextNode.children.length > 0) {
const nextChild = nextNode.children[];
if (nextChild === node.children[1]) {
return false;
}
}
}
}
}
return true;
// 显示树状图 function renderTree(nodes) { const root = nodes.find(node => node.parent === null)[]; const tree = { root, children: [] };
nodes.forEach((node, id) => {
if (node.children.length === 0) {
tree.children.push({ id, parent: node });
} else {
tree.children[].children.push({ id, parent: node });
}
});
// 画树状图
const drawTree = () => {
const ctx = document.documentElement.getContext('2d');
const nodeList = [];
for (let i = 1; i <= nodes.length; i++) {
const node = nodes[i];
nodeList.push({
id: i,
x: ctx.c getCoordinate('2d', 'root.x'),
y: ctx.c getCoordinate('2d', 'root.y'),
children: node.children.map(c => ({
x: ctx.c getCoordinate('2d', 'root.x') + c.id * 1,
y: ctx.c getCoordinate('2d', 'root.y'),
isChild: true,
label: c.id
})),
label: node.id
});
}
drawTreeQuiver(nodeList);
};
// 绘制树状图
drawTree();
// 可选性:删除节点 function deleteNodes(nodeId) { nodes[nodeId].isRemoved = true; document.body.removeChild({ 'node': { id: nodeId, parent: node.parent, children: node.children }, 'tree': { root: node.parent, children: node.children } }); }
// 用户反馈 function showFeedback(message) { alert(message); }
// 调用脚本 if (typeof window !== 'undefined') { createNode(); inputNodesAndRelationship(); showFeedback('输入节点和指向关系开始:'); // 等待用户输入 setTimeout(() => { inputNodesAndRelationship(); showFeedback('输入结束,系统检测完成:'); renderTree(nodes); }, 5); } else { document.body.removeChild({ 'node': { id: 1, parent: null, children: [] }, 'tree': { root: null, children: [] } }); } }
### 该脚本的功能和说明:
1. **节点输入界面**:
- 用户可以手动输入节点ID。
- 用户可以添加指向关系(从源节点到目标节点)。
2. **检测是否为梯子节点**:
- 系统检查输入的节点和指向关系是否形成一个有向无环图(DAG)。
- 如果存在环,系统提示用户删除节点或取消检查。
3. **树状图展示**:
- 系统会自动显示树状图,帮助用户直观理解节点和指向关系。
4. **反馈机制**:
- 用户每次输入后,系统会显示反馈(如成功检测、错误输入或删除节点)。
5. **可扩展性**:
- 系统支持用户多次输入数据,自动处理并及时反馈结果。
- 如果用户添加新的节点或指向关系,系统会自动调整并重新计算。
### 注意事项:
- 用户在输入节点ID时,请按照“节点ID”开始输入。
- 用户在添加指向关系时,请按照“源节点ID”开始输入。
- 用户在输入错误或未正确输入数据时,请及时重新输入。
这个脚本可以用于手动输入梯子节点,或者作为一个脚本在其他应用中自动处理节点检测。



