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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 求教一个用jspjavabean求解累加和的问题

    求教一个用jspjavabean求解累加和的问题JSP1      对输入的两个数字之间的数进行累加求和     初值:    末值:                  JSP2                     初值:  末值:  累加结果:   javabean文件package ExBean;pub

    2022年7月27日
    1
  • java float四舍五入保留两位小数,java四舍五入float保留两位小数

    java float四舍五入保留两位小数,java四舍五入float保留两位小数摘要腾兴网为您分享:java四舍五入float保留两位小数,远离手机,相机美颜,未来屋,微视等软件知识,以及流光,证券从业随身学,老a工具箱,polarr,特斯拉app,ae插件合集,福奈特,app名称,哈士奇表情,电视台直播源,思兔,门海,电子台账软件,3c电池,smartflashrecovery等软件it资讯,欢迎关注腾兴网。四舍五入我们大家都知道是什么但在java中四舍五入函数是什么如何…

    2022年5月21日
    54
  • 虚拟机fedora安装教程_潜水艇下水器安装图解

    虚拟机fedora安装教程_潜水艇下水器安装图解图解VMware下安装Fedora12前提条件1.安装了VMware2.下载Fedora12下载地址:http://fedoraproject.org/get-fedora  安装过程如下 1.启动新建虚拟机 2.选择Fedora12的ISO安装文件 3.选择虚拟机安装位置 4.设置虚拟机空间大小 5.设置虚拟机

    2022年9月20日
    0
  • 点击scrollview释放键盘触发touchesBegan方法

    点击scrollview释放键盘触发touchesBegan方法scrollView 本身继承了touch的响应事件,要从新自定义scrollView 的响应事件。所以添加一个手势事件:-(void)addGestureRecognizer{  UITapGestureRecognizer*sigleTap=[[UITapGestureRecognizeralloc]initWithTarget

    2022年7月25日
    9
  • 手机怎么模拟125k卡_NFC手机能模拟门禁卡吗?

    手机怎么模拟125k卡_NFC手机能模拟门禁卡吗?支持官方ROM的手机小米、华为、一加、索尼、三星(s4、s5、note3)、google亲儿子、魅族、LG、HTC、努比亚、乐视、moto、联想……不支持官方ROM的手机三星s6、s6e、s7、s7e、s8、s8+等等(官方rom不支持,但刷第三方rom支持,比如三星极光ROM)支持的手表Watch华为Watch2……支持的卡id”NFC卡模拟”能添加和模拟4字节、7字节和10字…

    2022年5月6日
    195
  • 如何优雅地送妹子礼物给她_怎样送女生礼物让女生接受

    如何优雅地送妹子礼物给她_怎样送女生礼物让女生接受一颗林萌 ,剁手已剁成哆啦A梦。刘巍然-学酥 等 15240 人赞同—————————————————————————————–有转载需要请私信,不接受未通知作者本人直接转载的行为,按原创法规直接举报。因为工作原因经常接触买买买,加上生活里经常剁手.

    2022年10月4日
    0

发表回复

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

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