Trie 树内存消耗问题

Trie 树内存消耗问题

大家都知道,Trie树(又称字典树)是一种树型数据结构,用于保存大量的字符串。它的优点是:利用字符串的公共前缀来节约存储空间。

相对来说,Trie树是一种比较简单的数据结构,比较易于理解。话说上帝是公平的,简单的东西是要付出相应的代价的!Trie树也有它的缺点,它的内存消耗非常大。下面介绍一个减小内存消耗的小技巧。

    我们先看看这个题目:http://acm.sdut.edu.cn/judgeonline/showproblem?problem_id=1500

    看看这段程序:

 

复制代码
复制代码
#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef struct node
{
int flag;
struct node *next[26];
}Node;
int tmp;
Node * NewNode()
{
int i;
Node * p = (Node *)malloc(sizeof(Node));
p->flag =0;
for(i =0; i <26; i++)
p->next[i] =0;
return p;
}
void insert(Node * root, char s[])
{
int n = strlen(s);
int i;
Node * p;
p = root;
for(i =0; i < n; i++)
{
if(p->next[s[i] -'a'] == NULL)
p->next[s[i] -'a'] = NewNode();
p = p->next[s[i] -'a'];
}
p->flag =1;
}
void search(Node * root, char s[])
{
int len = strlen(s);
int i;
Node *p;
p = root;
for(i =0; i < len; i++)
{
if(p->next[s[i] -'a'] != NULL)
p = p->next[s[i] -'a'];
}
if(p->flag)
{
p->flag =0;
tmp--;
}
}

void change(char s[])
{
int len, i;
len = strlen(s);
for(i =0; i < len; i++)
if(s[i] >='A'&& s[i] <='Z')
s[i] +=32;
}
int main()
{
int n, m;
char s[11];
Node *root;
while(scanf("%d", &n),n)
{
tmp = n;
scanf("%d", &m);
root = NewNode();
while(n--)
{
scanf("%s", s);
change(s);
insert(root, s);
}
while(m--)
{
scanf("%s", s);
change(s);
search(root, s);
}
printf("%d\n", tmp);
}
return0;
}
复制代码
复制代码

   

    这是一个典型的Trie树程序,AC的结果是:

160138 vongang 1500 Accepted 50376K 312MS GCC

 

    显然,memory很变态!

    从上边程序可以看到。root 在while(scanf(“%d”, &n),n)里边初始化,当一次while(scanf(“%d”, &n),n)执行完以后,第二次又会给root重新分配空间。这样,原来分配的空间就没有用处了,于是,我们可以在一次程序执行完以后,将root的空间free掉。当然不是简单的free(root),这里需要一个del()函数,代码如下:

 

 

复制代码
复制代码
void del(Node * p)
{
int i;
if(p) //p不为空
{
for(i =0; i <26; i++)
if(p->next[i])
del(p->next[i]); //递归删除每一个p->next[]
}
free(p);
p = NULL;
}
复制代码
复制代码

 

 

    在while(scanf(“%d”, &n),n){}的最后调用del()函数可以大大减小内存消耗, AC结果:

160137 vongang 1500 Accepted 12680K 500MS GCC

   

    memory从5W缩小到1W多,当然,时间有所增加,这也算是del()函数的一点缺陷吧。另为,此方法只适用于动态分配存储空间!

 

    作者:VonGang

    转载请注明:http://www.cnblogs.com/vongang/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101751.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • pycharm不小心删除文件怎么恢复_python恢复数据

    pycharm不小心删除文件怎么恢复_python恢复数据步骤1、点击被删除文件的所属上级目录右键;2、弹出的右键菜单点击localhistory,showhistory3、打开本地历史界面后,点击误删除文件;4、在右侧区域,选中文件,点击右键;5、在右键菜单中点击revertselection即可恢复;…

    2022年8月29日
  • Vue(4)Vue指令的学习1

    Vue(4)Vue指令的学习1前言Vue官网一共有提供了14个指令,分别如下v-textv-htmlv-showv-if☆☆☆v-else☆☆☆v-else-if☆☆☆v-for☆☆☆v-on☆☆☆v

    2022年7月29日
  • 我的世界java指令_我的世界java在哪下载

    我的世界java指令_我的世界java在哪下载Minecraft地图上的x,y和z坐标。以俯视的视角展示了X和Z轴的图像。红色高亮表示与标准不同的轴。坐标(coordinates)在数字上反映了玩家在世界中的位置。坐标基于一个由互相垂直且交于一点(即原点)的三条坐标轴形成的网格,即一个空间直角坐标系。x轴的正方向为东,其坐标反映了玩家距离原点在东(+)西(-)方向上的距离。z轴的正方向为南,其坐标反映了玩家距离原点在南(+)北(-)…

    2022年9月23日
  • 硬件设计中,总有一种想法让你冲动

    硬件设计中,总有一种想法让你冲动

    2022年3月4日
  • 字符串-字典树_求一个字符串的所有子串

    字符串-字典树_求一个字符串的所有子串HDU-1251统计难题POJ-3603PhoneListAcWing-143最大异或对HDU-5536ChipFactory字典树,顾名思义是以树结构来模拟字典。回想我们查字典的过程,比如查找”man”,先翻到字典m部分,再翻第二个字母a和第三个字母n,一共查找3次。查找次数最多是等于个单词的长度。插入查找单词的时间复杂度时O(m)O(m),此外有公共前缀的单词只需存一次公共前缀,节省了空间。

    2022年9月6日
  • linux 文件锁

    linux 文件锁1.文件锁基本概念Linux中软件、硬件资源都是文件(一切皆文件),文件在多用户环境中是可共享的。文件锁是用于解决资源的共享使用的一种机制:当多个用户需要共享一个文件时,Linux通常采用的方法是给文件上锁,来避免共享的资源产生竞争的状态。文件锁包括建议性锁和强制性锁:建议性锁:要求每个使用上锁文件的进程都要检查是否有锁存在,并且尊重已有的锁。在一般情况下,内核和系统都不使用建议性锁,它们依靠程序员遵守这个规定。强制性锁:是由内核执行的锁,当一个文件被上锁进行写入操作的时候,内核将阻止其他任何

    2022年6月28日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号