C语言 百分网手机站

C语言中压缩字符串的算法

时间:2020-10-04 11:49:27 C语言 我要投稿

C语言中压缩字符串的算法

  在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 < b->freq;

  }

  };

  void init()

  {

  for(int i = 0; i < Size; ++i)

  freq[i] = 0;

  for(int i = 0; i < word.size(); ++i)

  ++freq[word[i]];

  }

  void dfs(Node *root, string res)

  {

  if(root->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 Nodes(Node *root)

  {

  if(NULL == root)

  return ;

  if(NULL == root->left && NULL == root->right)

   root;

  else

  {

  Nodes(root->left);

  Nodes(root->right);

   root;

  }

  }

  void BuildTree()

  {

  priority_queue<Node*, vector, NodeLess> nodes;

  for(int i = 0; i < Size; ++i)

  {

  //0 == freq[i] 的情况未处理

  Node *newNode = new Node(freq[i]);

  newNode->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(""));

  Nodes(root);

  }

【C语言中压缩字符串的算法】相关文章:

C语言字符串快速压缩算法代码12-23

C语言中实现KMP算法实例11-19

C语言中返回字符串函数的实现方法12-15

c语言中关于使用BF-KMP算法实例11-21

c语言中用字符串数组写菜单的代码11-19

C语言中三种常见排序算法分析12-13

C 语言中返回字符串函数的四种实现方法11-16

C语言中使用快速排序算法对元素排序的实例12-01

c语言中冒泡排序、插入排序、选择排序算法比较12-12