字典树

本文深入解析字典树TrieNode的实现原理,基于哈希表构建节点,涵盖添加、删除单词,以及查找建议等功能。理解TrieNode如何通过子节点管理和标记完整单词,适用于词汇搜索和自动补全等应用场景。

字典树如图所示:

TrieNode.js:在hashTable的基础上实现的

import HashTable from '../hash-table/HashTable';

export default class TrieNode {//字典树节点类
  /**
   * @param {string} character
   * @param {boolean} isCompleteWord
   */
  constructor(character, isCompleteWord = false) {
    this.character = character;//当前字典树节点的字母
    this.isCompleteWord = isCompleteWord;//是否是一个完整的单词
    this.children = new HashTable();//children子节点,新的哈希表
  }

  /**
   * @param {string} character
   * @return {TrieNode}
   */
  getChild(character) {//从children哈希表中获取指定字母
    return this.children.get(character);
  }

  /**
   * @param {string} character
   * @param {boolean} isCompleteWord
   * @return {TrieNode}
   */
  addChild(character, isCompleteWord = false) {//给当前节点添加新的子节点
    if (!this.children.has(character)) {
      //如果children哈希表属性里没有这个字母,就用哈希表的set方法添加
      //key是字母,value是这个字母新建的字典树节点
      this.children.set(character, new TrieNode(character, isCompleteWord));
    }

    const childNode = this.children.get(character);
    //如果children哈希表中已经有这个字母了,获取到这个字典树节点

    // In cases similar to adding "car" after "carpet" we need to mark "r" character as complete.
    childNode.isCompleteWord = childNode.isCompleteWord || isCompleteWord;
    //更新它的isCompleteWord属性

    return childNode;//返回这个新字典树节点
  }

  /**
   * @param {string} character
   * @return {TrieNode}
   */
  removeChild(character) {//删除当前节点指定字母的子节点
    const childNode = this.getChild(character);//从children哈希表中获取指定字母的子节点

    // Delete childNode only if:
    // - childNode has NO children,
    // - childNode.isCompleteWord === false.
    if (
      childNode
      && !childNode.isCompleteWord
      && !childNode.hasChildren()
    ) {//如果存在childNode,并且childNode不是完整单词,并且childNode没有子节点
      this.children.delete(character);//满足上述条件就可以删除
    }

    return this;
  }

  /**
   * @param {string} character
   * @return {boolean}
   */
  hasChild(character) {//判断当前字典表节点有没有指定字母的子节点
    return this.children.has(character);
  }

  /**
   * Check whether current TrieNode has children or not.
   * @return {boolean}
   */
  hasChildren() {//判断当前字典表节点有没有子节点
    return this.children.getKeys().length !== 0;
  }

  /**
   * @return {string[]}
   */
  suggestChildren() {//返回当前字典表节点的所有子节点的字母组成的数组
    return [...this.children.getKeys()];
  }

  /**
   * @return {string}
   */
  toString() {
    let childrenAsString = this.suggestChildren().toString();//当前字典表节点的所有子节点的字母的数组的字符串形式
    childrenAsString = childrenAsString ? `:${childrenAsString}` : '';
    const isCompleteString = this.isCompleteWord ? '*' : '';//当前字典表节点是否是完整单词属性的字符串值

    return `${this.character}${isCompleteString}${childrenAsString}`;
    //返回当前字典表节点的字母,是否是完整单词字符串值,和所有子节点字母值连起来的字符串
  }
}

note:

1.对于toString的理解:找到改结点所有孩子的关键字,并且转为字符,通过isCompleteString判断是否为完整的字符,然后输出显示。

const trieNode = new TrieNode('c');

    trieNode.addChild('a', true);
    trieNode.addChild('o');

    expect(trieNode.toString()).toBe('c:a,o');

 Trie:

import TrieNode from './TrieNode';

// Character that we will use for trie tree root.
const HEAD_CHARACTER = '*';

export default class Trie {
  constructor() {
    this.head = new TrieNode(HEAD_CHARACTER);
  }

  /**
   * @param {string} word
   * @return {Trie}
   */
  addWord(word) {
    const characters = Array.from(word);
    let currentNode = this.head;

    for (let charIndex = 0; charIndex < characters.length; charIndex += 1) {
      const isComplete = charIndex === characters.length - 1;
      currentNode = currentNode.addChild(characters[charIndex], isComplete);
    }

    return this;
  }

  /**
   * @param {string} word
   * @return {Trie}
   */
  deleteWord(word) {
    const depthFirstDelete = (currentNode, charIndex = 0) => {
      if (charIndex >= word.length) {
        // Return if we're trying to delete the character that is out of word's scope.
        return;
      }

      const character = word[charIndex];
      const nextNode = currentNode.getChild(character);

      if (nextNode == null) {
        // Return if we're trying to delete a word that has not been added to the Trie.
        return;
      }

      // Go deeper.
      depthFirstDelete(nextNode, charIndex + 1);

      // Since we're going to delete a word let's un-mark its last character isCompleteWord flag.
      if (charIndex === (word.length - 1)) {
        nextNode.isCompleteWord = false;
      }

      // childNode is deleted only if:
      // - childNode has NO children
      // - childNode.isCompleteWord === false
      currentNode.removeChild(character);
    };

    // Start depth-first deletion from the head node.
    depthFirstDelete(this.head);

    return this;
  }

  /**
   * @param {string} word
   * @return {string[]}
   */
  suggestNextCharacters(word) {
    const lastCharacter = this.getLastCharacterNode(word);

    if (!lastCharacter) {
      return null;
    }

    return lastCharacter.suggestChildren();
  }

  /**
   * Check if complete word exists in Trie.
   *
   * @param {string} word
   * @return {boolean}
   */
  doesWordExist(word) {
    const lastCharacter = this.getLastCharacterNode(word);

    return !!lastCharacter && lastCharacter.isCompleteWord;
  }

  /**
   * @param {string} word
   * @return {TrieNode}
   */
  getLastCharacterNode(word) {
    const characters = Array.from(word);
    let currentNode = this.head;

    for (let charIndex = 0; charIndex < characters.length; charIndex += 1) {
      if (!currentNode.hasChild(characters[charIndex])) {
        return null;
      }

      currentNode = currentNode.getChild(characters[charIndex]);
    }

    return currentNode;
  }
}

总结:有点难,因为没有接触过,总的来说就是对着代码,看懂youtube上截过来的那张图。

转载于:https://www.cnblogs.com/Archer-Fang/p/10241547.html

多角色体系 支持管理员、商家、消费者三种角色,权限分级管控: 管理员:负责平台整体配置、用户审核、数据监控等全局操作。 商家:管理店铺信息、发布商品、处理订单、回复评价等。 消费者:浏览商品、加入购物车、下单支付、评价商品等。 实现用户注册(手机号 / 邮箱验证)、登录(支持密码 / 验证码 / 第三方登录)、个人信息管理(头像、收货地址、密码修改)。 权限精细化控制 商家仅能管理自家店铺及商品,消费者仅能查看和购买商品,管理员拥有全平台数据访问权限。 二、商品管理功能 商品信息维护 商家可发布商品:填写名称、分类(如服饰、电子产品)、子类别(如手机、笔记本)、规格(尺寸、颜色、型号)、价格、库存、详情描述(图文)、物流信息(运费、发货地)等。 支持商品上下架、库存调整、信息编辑,系统自动记录商品状态变更日志。 商品分类与搜索 按多级分类展示商品(如 “数码产品→手机→智能手机”),支持自定义分类体系。 提供智能搜索功能:按关键词(名称、品牌)搜索,支持模糊匹配和搜索联想;结合用户浏览历史对搜索结果排序(优先展示高相关度商品)。 商品推荐 基于用户浏览、收藏、购买记录,推荐相似商品(如 “浏览过该商品的用户还买了…”)。 首页展示热门商品(销量 TOP10)、新品上架、限时折扣等推荐列表。 三、订单与交易管理 购物车与下单 消费者可将商品加入购物车,支持修改数量、选择规格、移除商品,系统自动计算总价(含运费、折扣)。 下单流程:确认收货地址→选择支付方式(在线支付、货到付款)→提交订单→系统生成唯一订单号。 订单处理流程 订单状态跟踪:待支付→已支付→商家发货→物流运输→消费者收货→订单完成,各状态变更实时通知用户。 商家端功能:查看新订单提醒、确认发货(填写物流单号)、处理退款申请(需审核理由)。 消费者端功能:查看订单详情、追踪物流、申请退款 / 退货、确认收货。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值