Skip to content

Commit 0da65e0

Browse files
committed
fix: find linear paths correctly
1 parent cb69cc9 commit 0da65e0

File tree

4 files changed

+497
-355
lines changed

4 files changed

+497
-355
lines changed

src/suggest/filter.ts

Lines changed: 71 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,30 +77,86 @@ export function onlyFunctions(
7777
// ---
7878

7979
export function findLinearPaths(graph: Map<TypedNode, Set<TypedNode>>) {
80-
const linearPaths = [];
81-
82-
const visitedNodes = new Set();
80+
const linearPaths = [] as TypedNode[][];
81+
const visitedNodes = new Set<TypedNode>();
82+
const nodeInDegrees = new Map<TypedNode, number>();
8383

84+
// 计算每个节点的入度
8485
for (const [node, edges] of graph.entries()) {
85-
if (edges.size === 1 && !visitedNodes.has(node)) {
86-
const path = [node];
87-
let nextNode = Array.from(edges)[0];
86+
for (const edge of edges) {
87+
const inDegree = nodeInDegrees.get(edge) || 0;
88+
nodeInDegrees.set(edge, inDegree + 1);
89+
}
90+
}
91+
92+
function dfs(node: TypedNode, path: TypedNode[]) {
93+
if (visitedNodes.has(node)) {
94+
return;
95+
}
96+
97+
path.push(node);
98+
visitedNodes.add(node);
8899

89-
visitedNodes.add(node);
100+
const edges = graph.get(node) || new Set();
101+
102+
if (edges.size === 0 || edges.size > 1) {
103+
if (path.length > 1) {
104+
addOrUpdatePath([...path]);
105+
}
106+
}
107+
else {
108+
const nextNode = Array.from(edges)[0];
109+
const nextNodeInDegree = nodeInDegrees.get(nextNode) || 0;
110+
111+
// 确保下一个节点只有一个入度
112+
if (nextNodeInDegree === 1) {
113+
dfs(nextNode, path);
114+
}
115+
}
116+
117+
path.pop();
118+
visitedNodes.delete(node);
119+
}
90120

91-
while (graph.get(nextNode)?.size === 1) {
92-
if (visitedNodes.has(nextNode)) {
121+
function addOrUpdatePath(newPath: TypedNode[]) {
122+
let shouldAddNewPath = true;
123+
124+
for (let i = linearPaths.length - 1; i >= 0; i--) {
125+
const existingPath = linearPaths[i];
126+
if (isSubpath(existingPath, newPath)) {
127+
linearPaths.splice(i, 1); // remove the shorter path
128+
}
129+
else if (isSubpath(newPath, existingPath)) {
130+
shouldAddNewPath = false;
131+
break;
132+
}
133+
}
134+
135+
if (shouldAddNewPath && newPath.length > 2) {
136+
linearPaths.push(newPath);
137+
}
138+
}
139+
140+
function isSubpath(shortPath: TypedNode[], longPath: TypedNode[]) {
141+
if (shortPath.length >= longPath.length) { return false; }
142+
143+
for (let i = 0; i <= longPath.length - shortPath.length; i++) {
144+
let isSub = true;
145+
for (let j = 0; j < shortPath.length; j++) {
146+
if (shortPath[j] !== longPath[i + j]) {
147+
isSub = false;
93148
break;
94149
}
95-
path.push(nextNode);
96-
visitedNodes.add(nextNode);
97-
nextNode = Array.from(graph.get(nextNode)!)[0];
98150
}
99-
100-
if (path.length > 1) {
101-
linearPaths.push(path);
151+
if (isSub) {
152+
return true;
102153
}
103154
}
155+
return false;
156+
}
157+
158+
for (const node of graph.keys()) {
159+
dfs(node, []);
104160
}
105161

106162
return linearPaths;

0 commit comments

Comments
 (0)