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"));
+ }
+}