godoos/frontend/src/util/Tree.ts
2024-07-22 17:44:55 +08:00

72 lines
1.9 KiB
TypeScript

class Tree<T> {
value: T;
children: Tree<T>[] = [];
constructor(value?: T, children?: Tree<T>[]) {
this.value = value || ({} as T);
this.children = children || [];
}
addChild(child: T) {
this.children.push(new Tree(child));
}
removeChild(child: T) {
this.children = this.children.filter((node) => node.value !== child);
}
findNode(value: T, callBack?: (val: Tree<T>) => void): Tree<T> | undefined {
// find node by dfs in children
for (const child of this.children) {
if (child.value === value) {
if (callBack) {
callBack(child);
}
return child;
} else {
const node = child.findNode(value, callBack);
if (node) return node;
}
}
return undefined;
}
removeNode(value: T) {
// find node by dfs in children and remove it
this.children = this.children.filter((child) => {
if (child.value === value) return false;
child.removeNode(value);
return true;
});
}
findIndex(value: T, filter: (value: Tree<T>, index: number, array: Tree<T>[]) => boolean): number {
// nth children index
let index = 0;
for (const child of this.children.filter(filter)) {
if (child.value === value) {
return index;
} else {
let cindex = 0;
if (child.children.length > 0) {
cindex = child.findIndex(value, filter);
}
index += cindex + 1;
}
}
return -1;
}
traverseBFS(fn: (node: Tree<T>) => void) {
const arr: Tree<T>[] = [this];
while (arr.length) {
const node = arr.shift();
if (!node) continue;
arr.push(...node.children);
fn(node);
}
}
traverseDFS(fn: (node: Tree<T>) => void) {
const arr: Tree<T>[] = [this];
while (arr.length) {
const node = arr.shift();
if (!node) continue;
arr.unshift(...node.children);
fn(node);
}
}
}
export { Tree };