js版本单词查找树1.0_null

//不熟悉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()
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值