热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

C语言中压缩字符串的简单算法小结

这篇文章主要介绍了C语言中可用于实现字符串压缩的简单算法小结,列举了包括哈夫曼算法等三个核心的程序实现算法,需要的朋友可以参考下

应用中,经常需要将字符串压缩成一个整数,即字符串散列。比如下面这些问题:
(1)搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。请找出最热门的10个检索串。
(2)有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。
(3)有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序。
(4)给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url。
(5)一个文本文件,大约有一万行,每行一个词,要求统计出其中最频繁出现的前10个词。

这些问题都需要将字符串压缩成一个整数,或者说是散列到某个整数 M 。然后再进行取余操作,比如 M%16,就可以将该字符串放到编号为M%16的文件中,相同的字符串肯定是在同一个文件中。通过这种处理,就可以将一个大文件等价划分成若干小文件,而对于小文件,就可以用常规的方法处理,内排序、hash_map等等。最后将这些小文件的处理结果综合起来,就可以求得原问题的解。
下面介绍一些字符串压缩的算法。

方法1:最简单就是将所有字符加起来,代码如下:

unsigned long HashString(const char *pString, unsigned long tableSize)
{
 unsigned long hashValue = 0;
 while(*pString)
    hashValue += *pString++;
 return hashValue % tableSize;
}

分析:如果字符串的长度有限,而散列表比较大的话,浪费比较大。例如,如果字符串最长为16字节,那么用到的仅仅是散列表的前16*127=2032。假如散列表含2729项,那么2032以后的项都用不到。

方法2:将上次计算出来的hash值左移5位(乘以32),再和当前关键字相加,能得到较好的均匀分布的效果。

unsigned long HashString(const char *pString,unsigned long tableSize)
{
 unsigned long hashValue = 0;
 while (*pString)
 hashValue = (hashValue <<5) + *pString++;
 return hashValue % tableSize;
}

分析:这种方法需要遍历整个字符串,如果字符串比较大,效率比较低。

方法3:利用哈夫曼算法,假设只有0-9这十个字符组成的字符串,我们借助哈夫曼算法,直接来看实例: 

#define Size 10 
int freq[Size]; 
string code[Size]; 
string word; 
struct Node 
{ 
 int id; 
 int freq; 
 Node *left; 
 Node *right; 
 Node(int freq_in):id(-1), freq(freq_in) 
 { 
  left = right = NULL; 
 } 
}; 
struct NodeLess 
{ 
 bool operator()(const Node *a, const Node *b) const 
 { 
  return a->freq freq; 
 } 
}; 
 
void init() 
{ 
 for(int i = 0; i id >= 0) 
  code[root->id] = res; 
 else 
 { 
  if(NULL != root->left) 
   dfs(root->left, res+"0"); 
  if(NULL != root->right) 
   dfs(root->right, res+"1"); 
 } 
} 
 
void deleteNodes(Node *root) 
{ 
 if(NULL == root) 
  return ; 
 if(NULL == root->left && NULL == root->right) 
  delete root; 
 else 
 { 
  deleteNodes(root->left); 
  deleteNodes(root->right); 
  delete root; 
 } 
} 
void BuildTree() 
{ 
 priority_queue, NodeLess> nodes; 
 for(int i = 0; i id = i; 
  nodes.push(newNode); 
 } 
 while(nodes.size() > 1) 
 { 
  Node *left = nodes.top(); 
  nodes.pop(); 
  Node *right = nodes.top(); 
  nodes.pop(); 
  Node *newNode = new Node(left->freq + right->freq); 
    newNode->left = left; 
    newNode->right = right; 
    nodes.push(newNode); 
 } 
 Node *root = nodes.top(); 
 dfs(root, string("")); 
 deleteNodes(root); 
} 


推荐阅读
  • 本文探讨了如何利用Java 8 Stream API 对数组进行高效排序和筛选处理。具体而言,通过 `stream()` 方法将 `listResult` 转换为流,然后使用 `sorted(Comparator.comparing())` 方法按伴随度进行降序排序,并最终收集结果。此外,还介绍了如何结合过滤条件进一步优化数据处理流程,提升代码的可读性和执行效率。 ... [详细]
  • HBase Java API 进阶:过滤器详解与应用实例
    本文详细探讨了HBase 1.2.6版本中Java API的高级应用,重点介绍了过滤器的使用方法和实际案例。首先,文章对几种常见的HBase过滤器进行了概述,包括列前缀过滤器(ColumnPrefixFilter)和时间戳过滤器(TimestampsFilter)。此外,还详细讲解了分页过滤器(PageFilter)的实现原理及其在大数据查询中的应用场景。通过具体的代码示例,读者可以更好地理解和掌握这些过滤器的使用技巧,从而提高数据处理的效率和灵活性。 ... [详细]
  • 在SWUSTOJ #1063中,题目要求对带权重的有向图进行算法计算与分析。假设图G使用邻接矩阵存储,任务是计算图中的最大权值和最小权值,并确定对应的有向边。输入数据的第一行包含一个整数n,表示图中节点的数量。随后的输入将提供图的边及其权重信息。通过该算法,可以有效地找出图中的关键路径和最短路径,为图论问题的解决提供重要参考。 ... [详细]
  • PHP 数组逆序排列方法及常用排序函数详解 ... [详细]
  • 本文深入探讨了二叉树路径和问题的算法优化方法。具体而言,给定一棵二叉树,需要找出所有从根节点到叶节点的路径,其中各节点值的总和等于指定的目标值。通过详细分析和优化,提出了一种高效的解决方案,并通过多个样例验证了其有效性和性能。 ... [详细]
  • 本文详细解析了高性能通信库 NanoMsg 的框架及其应用场景。其中,BUS模式支持多对多的简单通信方式,消息会传递给所有直接连接的节点。REQREP模式则适用于构建无状态的服务集群,用于处理用户的请求,每个请求都需要一个相应的响应。 ... [详细]
  • 投融资周报 | Circle 达成 4 亿美元融资协议,唯一艺术平台 A 轮融资超千万美元 ... [详细]
  • 二叉树的直径是指树中任意两个叶节点之间最长路径上的节点数量。本文深入解析了计算二叉树直径的算法,并提出了一种优化方法,以提高计算效率和准确性。通过详细的案例分析和性能对比,展示了该优化算法在实际应用中的优势。 ... [详细]
  • 本文详细探讨了YOLO目标检测技术在实际应用中的实践与优化。通过一系列实战案例,展示了如何在不同场景下高效部署和调优YOLO模型。验证环境包括Ubuntu 18.04、NVIDIA驱动450、CUDA 11.0、cuDNN 8.0.5和OpenCV 4.4.0,确保了模型的稳定性和高性能表现。文章将持续更新,提供最新的技术进展和实践经验。 ... [详细]
  • vtkGlyph3D 是一种强大的符号化可视化工具,能够将三维数据集中的每个点用预定义的几何图形(如球体或箭头)进行表示。该工具不仅支持自定义符号的方向和缩放比例,还能够在复杂的数据场中突出显示关键特征,从而提高数据的可解释性和可视化效果。通过这种方式,用户可以更直观地理解和分析三维数据集中的重要信息。 ... [详细]
  • 为了评估精心优化的模型与策略在实际环境中的表现,Google对其实验框架进行了全面升级,旨在实现更高效、更精准和更快速的在线测试。新的框架支持更多的实验场景,提供更好的数据洞察,并显著缩短了实验周期,从而加速产品迭代和优化过程。 ... [详细]
  • 本文提出了一种高效的数据结构与算法,旨在解决超大整数(超出常规 `long` 类型范围)的加法运算问题。通过引入自定义的数据结构,该方法能够有效地存储和处理任意大小的整数,并在保证计算精度的同时,显著提升运算效率。实验结果表明,该方法在处理大规模数据时表现出色,具有较高的实用价值。 ... [详细]
  • 本文详细介绍了Java编程中的几种重要技巧,包括冒泡排序和选择排序这两种基础的数组排序算法。冒泡排序通过多次遍历数组,将较大的元素逐步移动到数组末尾;而选择排序则在每次遍历中选择最小的元素并将其放置在正确的位置。此外,文章还探讨了二分查找算法,该算法适用于已排序的数组,能够高效地进行查找操作。同时,文中还介绍了Java中的`Arrays`类及其常用方法,以及如何进行进制转换和装箱与拆箱操作,提供了丰富的示例和注意事项,帮助读者深入理解这些核心概念。 ... [详细]
  • 本文详细解析了九度编程平台上的斐波那契数列高效算法挑战(题目编号:1387)。该挑战要求在1秒的时间限制和32兆的内存限制下,设计出高效的斐波那契数列计算方法。通过多种算法的对比和性能分析,本文提供了优化方案,帮助参赛者在限定资源条件下实现高效计算。 ... [详细]
  • 解决Android应用在手机安装时出现安全风险提示的方法与对策
    解决Android应用在手机安装时出现安全风险提示的方法与对策 ... [详细]
author-avatar
风行景逸-枣庄郊南店
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有