//不熟悉js的undefined,全写成null了
function getMap(){ //生成字母表
let words={}
for(let i=0;i<26;i++){
let c=String.fromCharCode(97+i)
words[c]=null
}
return words
}
//在node下获取key对应的val,d是即将比较的字符串的长度,如d=2表示即将用key的第2个字符与树对应的节点进行比较
function get(node,key,d=0){
if(node==null)return null
if(d==key.length)return node
return get(node.next[key[d]],key,d+1)
}
//在node下设置key对应的值是val,没有创建有就覆盖,d是即将比较的字符串的长度
//JSON.parse(JSON.stringify(getMap()))实现深复制的效果,避免地址引用
function put(node,key,val,d=0){
if(node==null){
var node={next:JSON.parse(JSON.stringify(getMap())),val:null}
}
if(d==key.length){
node.val=val
}else{
k=key[d]
node.next[k]=put(node.next[k],key,val,d+1)
}
return node
}
//keysWithPrefix:返回node节点下以pre开头的所有key,设置默认值的参数必须放最后,否则报错,d是即将比较的字符串的长度
function keysWithPrefix(node,pre,list=[],d=0){
if(node==null){return list}
if(node.val!=null&&d>=pre.length){list.push(pre)}
if(d>=pre.length){
for(let x in node.next){
let y=node.next[x]
if(y!=null){
list=keysWithPrefix(y,pre+x,list,d+1)
}
}
}else{
list=keysWithPrefix(node.next[pre[d]],pre,list,d+1)
}
return list
}
//keysThatMatch:返回匹配的字符串,如果a.b对应a[a-z]b
function keysThaMatch(node,match,list=[],pre=""){
if(node==null||pre.length>match.length){return list}
if(node.val!=null&&pre.length==match.length){list.push(pre)}
for(let x in node.next){
let d=pre.length
if(match[d]=='.'||match[d]==x){
let y=node.next[x]
if(y!=null){
list=keysThanMatch(y,match,list,pre+x)
}
}
}
return list
}
//longestPrefixOf:返回给定字符串最长公共前缀的key,d1是目前此key的长度,d2是即将比较的字符串的长度
//第一次执行时,d2=0表示即将比较根节点和match
function longestPrefixOf(node,match,d1=0,d2=0){
//console.log(d1,d2)
if(node==null||d2>match.length){return match.substr(0,d1)}
if(node.val!=null){d1=d2}
return longestPrefixOf(node.next[match[d2]],match,d1,d2+1)
}
//delete:d是即将比较的字符串的长度,删除key对应节点后,需要把无子节点且没有val的节点也删除
function delete_(node,key,d=0){
if(node==null){
return null
}
if(d==key.length){
node.val=null
}else{
k=key[d]
node.next[k]=delete_(node.next[k],key,d+1)
}
for(let i in node.next){ //node.val!=null的判断最好放循环外面,放里面影响不大
if(node.val!=null||node.next[i]!=null){return node}
}
return null
//return null不能省略,因为js没有返回值时返回undefined,实际逻辑需要null
}
//======================================
var root=null
let j1=require('./1')
let mylength=10000
randomWords=j1.getWords(mylength,1,5)
randomWords.forEach((x)=>{root=put(root,x,x+'Val')}) //put随机字符串到以root为根节点的树
console.log("\n\n\n\n\nrandomWords=\n",randomWords)
randomWords.forEach((x)=>{ //测试put是否生效
if(get(root,x)==null){
console.log(x+'---->'+get(root,x).value)
}
})
console.log('\n\n\n-->test keysWithPrefix')
console.log(keysWithPrefix(root,"a")) //打印以'a'开头的字符串
console.log(keysWithPrefix(root,"")) //打印以所有字符串
console.log(keysWithPrefix(root,"").length) //长度可能不到mylength,因为有重复的可以key:val
let matchstr="..."
console.log('\n\n\n-->test keysThanMatch '+matchstr)
console.log(list=keysThanMatch(root,matchstr))
let prefixstr="abcd"
console.log('\n\n\n-->test longestPrefixOf '+prefixstr)
console.log(longestPrefixOf(root,prefixstr))
console.log('\n\n\n-->test delete')
root=put(root,'aaaaaa','a6val')
root=put(root,'aaaaaaaa','a8val')
console.log(keysWithPrefix(root,"",[]))
console.log(get(root,"aaaaaaaa"))
console.log(get(root,"aaaaaaa"))
console.log(get(root,"aaaaaa"))
console.log(get(root,"aaaaa"))
root=delete_(root,'aaaaaaaa')
root=delete_(root,'a')
console.log(keysWithPrefix(root,"",[]))
console.log(get(root,"aaaaaaaa"))
console.log(get(root,"aaaaaaa"))
console.log(get(root,"aaaaaa"))
console.log(get(root,"aaaaa"))
//========================== 1.js代码
exports.getWords=function getWords(maxcount=20,minlen=0,maxlen=11){
let words=[]
for (let j=0;j<maxcount;j++){
let arr=''
let len_=minlen+Math.floor(Math.random()*(maxlen-minlen+1))
for(let l=0;l<len_;l++){
arr = arr + String.fromCharCode(97+Math.floor(Math.random()*26))
}
words.push(arr)
}
return words
}
exports.char2int=(a)=>{
return a==''?-1:a.charCodeAt()
}
js版本单词查找树1.0_null
最新推荐文章于 2023-07-21 02:44:12 发布