From 50f7bfcafa757c23693d79722566a8810ab08fba Mon Sep 17 00:00:00 2001 From: Nezuko-Wen <409053122@qq.com> Date: Mon, 22 Aug 2022 22:53:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=BC=80=E6=A0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +++ src/ds/tree/PrefixTree.java | 109 ++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 src/ds/tree/PrefixTree.java diff --git a/README.md b/README.md index 6e976e4..730fe32 100644 --- a/README.md +++ b/README.md @@ -140,3 +140,11 @@ eg: [1,3,4,2,5]
2的小数:1
5的小数:1,3,4,2
小数和为:1+1+3+1+1+3+4+2 + +### 前缀树 +1)单个字符串中,字符从前到后的加到一棵多叉树上
+2)字符放在边上,节点上有专属的数据项(常见的是pass和end值)
+3)样本添加方式,每个字符串都从根节点开始加,如果没有路就新建,如果有路就复用
+4)添加时,沿途节点的pass值加1,每个字符串结束时来到的节点end值加1
+ +end值可查某个字符串出现几次,pass值可查以某个字符串为前缀的字符串出现过几次 diff --git a/src/ds/tree/PrefixTree.java b/src/ds/tree/PrefixTree.java new file mode 100644 index 0000000..fd31593 --- /dev/null +++ b/src/ds/tree/PrefixTree.java @@ -0,0 +1,109 @@ +package ds.tree; + +/** + * @author Wen + * @date 2022/8/22 22:26 + */ +public class PrefixTree { + private Node head; + + public PrefixTree() { + head = new Node(); + } + + //将字符串插入前缀树中 + public void insert(String str) { + if (str == null) { + return; + } + Node node = head; + node.pass++; + char[] chars = str.toCharArray(); + for (char aChar : chars) { + int index = aChar - 'a';//在哪个节点上 + if (node.next[index] == null) { + node.next[index] = new Node(); + } + node.next[index].pass++; + node = node.next[index]; + } + node.end++; + } + + //str出现过几次 + public Integer search(String str) { + if (str == null) { + return 0; + } + Node node = head; + char[] chars = str.toCharArray(); + for (char aChar : chars) { + int index = aChar - 'a';//在哪个节点上 + if (node.next[index] == null) { + return 0; + } + node = node.next[index]; + } + return node.end; + } + + public void delete(String str) { + if (search(str) > 0) { + Node node = head; + node.pass--; + char[] chars = str.toCharArray(); + for (char aChar : chars) { + int index = aChar - 'a';//在哪个节点上 + if (--node.next[index].pass == 0) {//pass为0后,后面节点直接丢弃 + node.next[index] = null; + return; + } + node = node.next[index]; + } + node.end--; + } + } + + //以prefix为前缀的字符串个数 + public Integer prefixNumber(String prefix) { + if (prefix == null) { + return 0; + } + Node node = head; + char[] chars = prefix.toCharArray(); + for (char aChar : chars) { + int index = aChar - 'a';//在哪个节点上 + if (node.next[index] == null) { + return 0; + } + node = node.next[index]; + } + return node.pass; + } + + class Node { + int pass; + int end; + Node[] next; + + public Node() { + this.pass = 0; + this.end = 0; + next = new Node[26];//假设字符串都是26个小写字母 + } + } + + public static void main(String[] args) { + PrefixTree prefixTree = new PrefixTree(); + prefixTree.insert("abc"); + prefixTree.insert("abc"); + prefixTree.insert("eewd"); + prefixTree.insert("adb"); + prefixTree.insert("eewd"); + prefixTree.insert("abs"); + prefixTree.insert("eewd"); + System.out.println(prefixTree.search("abc")); + System.out.println(prefixTree.search("eewd")); + System.out.println(prefixTree.prefixNumber("ab")); + } +}