最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
字典树(前缀树)链表实现代码模板(C/C++/Java/Python多版本)
时间:2026-08-13 12:13:50 编辑:袖梨 来源:一聚教程网
字典树(前缀树)链表实现代码模板(C/C++/Java/Python多版本)需要先看清适用场景和关键步骤,避免只记结论却忽略实际限制。
字典树又称前缀树,是一种专门用于高效存储和检索字符串集合的树形数据结构,其核心思想是利用字符串的公共前缀来减少存储空间并加速查询:每个节点代表一个字符,从根节点到任意节点的路径构成一个字符串前缀,通过共享前缀分支来优化存储,并支持快速的插入、查找和前缀匹配操作,广泛应用于搜索引擎自动补全、拼写检查和IP路由等场景。本节的代码模板将向您展示如何通过链表模拟来实现字典树。

链表模拟的特点是功能丰富、支持删除和重复字符串、内存灵活、扩展性强。相较于数组模拟实现字典树来说,其缺点也不容小觑:存在动态内存分配开销大、代码复杂、存在内存泄漏风险、实现难度较高等问题。
1. C/C++版代码:
// 一个以链表实现带删除功能允许重复字符串的字典树#include <stdio.h>#include <string.h>#include <stdlib.h>int charmapping[256]; // 字符映射数组,-1表示无效字符void init_charmapping() { // 初始化所有字符为无效值 for (int i = 0; i < 256; i++) { charmapping[i] = -1; } // 只允许输入小写字符组成的字符串 for (int i = 'a'; i <= 'z'; i++) { charmapping[i] = i - 'a'; }}const int maxn = 26;struct treenode { int count; treenode* next[maxn];} head;void init_trie() { head.count = 1; // 初始化为1包括空串并且避免树头被删 for (int i = 0; i < maxn; i++) { head.next[i] = NULL; }}treenode* createnew() { treenode* newnode = (treenode*)malloc(sizeof(treenode)); newnode->count = 0; for (int i = 0; i < maxn; i++) { newnode->next[i] = NULL; } return newnode;}void update(char* s, int num) { int k = 0; treenode* t = &head; while (s[k]) { int temp = charmapping[(unsigned char)s[k]]; if (temp < 0) { // 非法字符 k++; continue; } t->count += num; if (!t->next[temp]) { t->next[temp] = createnew(); } t = t->next[temp]; k++; } t->count += num;}bool search(char* s, int num) { int k = 0; treenode* t = &head; while (s[k]) { int temp = charmapping[(unsigned char)s[k]]; if (temp < 0 || !t->next[temp] || t->next[temp]->count < num) { return false; } t = t->next[temp]; k++; } int snum = t->count; for (int i = 0; i < maxn; i++) { if (t->next[i]) { snum -= t->next[i]->count; } } return snum >= num;}//删除函数void erase(char* s, int num) { if (!search(s, num)) { return; } // 先减少所有相关节点的计数 int k = 0; treenode* t = &head; head.count -= num; while (s[k]) { int temp = charmapping[(unsigned char)s[k]]; if (temp < 0 || !t->next[temp]) { break; } t->next[temp]->count -= num; t = t->next[temp]; k++; } // 当前实现只减少计数,不实际释放节点,避免内存管理问题}// 递归释放所有节点void free_trie(treenode* node) { if (!node) return; for (int i = 0; i < maxn; i++) { if (node->next[i]) { free_trie(node->next[i]); node->next[i] = NULL; } } if (node != &head) { free(node); }}char temp[1000];void printall(treenode* tnode, int pos) { if (!tnode) return; int count = tnode->count; for (int i = 0; i < maxn; i++) { if (tnode->next[i]) { count -= tnode->next[i]->count; } } for (int i = 0; i < count; i++) { temp[pos] = '