效果:
[Running] ts-node "e:\1.project\front_end\js\script.ts"
所有单词: [ 'Tom', 'Toma', 'Tomas', 'Tomass' ]
以Tomas为前缀的所有单词: [ 'Tomas', 'Tomass' ]
以Toma为前缀的所有索引数据项: [
{ name: 'Toma', age: 13 },
{ name: 'Tomas', age: 14 },
{ name: 'Tomass', age: 15 }
]
type ChildrenList = Child[]
type Child =
| _DicNode
| any
type NodeValue =
| string
| null
type Word = string
class _DicNode{
private _letter: NodeValue;
private _children: any;
private _letters: string[];
private _value: any;
constructor (c: string) {
this._letter = c;
this._children = {};
this._letters = [];
this._value = null;
}
public getLetter = ():NodeValue => {
return this._letter;
}
public getLetters = ():NodeValue[] => {
return this._letters;
}
public getChild = (c: string):_DicNode => {
return this._children[c];
}
public getChildren = ():ChildrenList => {
return Object.values(this._children);
}
public putChild = (c: string, value = null) => {
if(this.containChild(c)) return;
this._letters.push(c);
this._children[c] = new _DicNode(c);
this._children[c]._value = value;
}
public getValue = () => {
return this._value;
}
public containChild = (c: string):boolean => {
return this._letters.indexOf(c) >= 0;
}
public size = () => {
return this._letters.length;
}
public clear = () => {
this._children = {}
this._letters = []
this._value = null;
}
}
export class DictionaryTree{
private _root: _DicNode;
constructor () {
this._root = new _DicNode('$');
}
public add = (word: string, value: any= null) => {
this._add(word, 0, this._root, value);
}
private _add = (word: string, idx: number, node: Child, value: any= null) => {
if(idx >= word.length) {
node.putChild('', value);
return
};
if(node.containChild(word[idx])){
this._add(word, idx + 1, node.getChild(word[idx]), value);
} else {
node.putChild(word[idx]);
const _n = node.getChild(word[idx]);
this._add(word, idx + 1, _n, value);
}
}
public findWordsByPrefix = (prefix: string): Word[] => {
if(prefix.length === 0) return [];
const _startNode: _DicNode = this._findNode(prefix, 0, this._root);
if(_startNode.getLetter() === '') return [];
return this._getAllWords(_startNode, prefix.substring(0, prefix.length-1));
}
private _findNode = (prefix: string, idx: number = 0, node: _DicNode): _DicNode => {
if(idx >= prefix.length) return new _DicNode('');
if(idx === prefix.length - 1) {
if(node.containChild(prefix[idx])){
return node.getChild(prefix[idx]);
} else {
return new _DicNode('');
}
};
if(node.containChild(prefix[idx])){
return this._findNode(prefix, idx + 1, node.getChild(prefix[idx]));
}
return new _DicNode('');
}
public clear = () => {
this._root.clear();
}
public getAllWords = (): Word[] => {
let _res: Word[] = [];
this._root.getChildren().forEach( (_node: Child) =>{
let _t = this._getAllWords(_node);
_res = [..._res, ..._t]
})
return _res;
}
private _getAllWords = (dicNode: _DicNode, prefix: string = ''): Word[] => {
const _prefix = prefix + dicNode.getLetter();
let _res: Word[] = [];
if(dicNode.size() == 0){
_res.push(prefix + dicNode.getLetter());
}
dicNode.getChildren().forEach((_node: Child)=>{
let _ws = this._getAllWords(_node, _prefix);
_res = [..._res, ..._ws];
})
return _res;
}
private _getValue = (word: Word) => {
const node = this._findNode(word, 0, this._root);
return node.getChild('').getValue();
}
public getDataByPrefix = (prefix: Word) => {
let _words = this.findWordsByPrefix(prefix);
let _res: any = []
_words.forEach(word=>{
let _data = this._getValue(word);
_data && _res.push(_data)
})
return _res;
}
}
const tree = new DictionaryTree();
tree.add("Tom", {name: "Tom", age: 12});
tree.add("Toma", {name: "Toma", age: 13});
tree.add("Tomas", {name: "Tomas", age: 14});
tree.add("Tomass", {name: "Tomass", age: 15});
console.log("所有单词: ", tree.getAllWords());
console.log("以Tomas为前缀的所有单词: ", tree.findWordsByPrefix("Tomas"));
console.log("以Toma为前缀的所有索引数据项: ", tree.getDataByPrefix("Toma"));