日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

C語言中壓縮字符串的簡單算法小結(jié)

 gearss 2016-04-14

應(yīng)用中,經(jīng)常需要將字符串壓縮成一個(gè)整數(shù),即字符串散列。比如下面這些問題:
(1)搜索引擎會通過日志文件把用戶每次檢索使用的所有檢索串都記錄下來,每個(gè)查詢串的長度為1-255字節(jié)。請找出最熱門的10個(gè)檢索串。
(2)有一個(gè)1G大小的一個(gè)文件,里面每一行是一個(gè)詞,詞的大小不超過16字節(jié),內(nèi)存限制大小是1M。返回頻數(shù)最高的100個(gè)詞。
(3)有10個(gè)文件,每個(gè)文件1G,每個(gè)文件的每一行存放的都是用戶的query,每個(gè)文件的query都可能重復(fù)。要求你按照query的頻度排序。
(4)給定a、b兩個(gè)文件,各存放50億個(gè)url,每個(gè)url各占64字節(jié),內(nèi)存限制是4G,讓你找出a、b文件共同的url。
(5)一個(gè)文本文件,大約有一萬行,每行一個(gè)詞,要求統(tǒng)計(jì)出其中最頻繁出現(xiàn)的前10個(gè)詞。

這些問題都需要將字符串壓縮成一個(gè)整數(shù),或者說是散列到某個(gè)整數(shù) M 。然后再進(jìn)行取余操作,比如 M%16,就可以將該字符串放到編號為M%16的文件中,相同的字符串肯定是在同一個(gè)文件中。通過這種處理,就可以將一個(gè)大文件等價(jià)劃分成若干小文件,而對于小文件,就可以用常規(guī)的方法處理,內(nèi)排序、hash_map等等。最后將這些小文件的處理結(jié)果綜合起來,就可以求得原問題的解。
下面介紹一些字符串壓縮的算法。

方法1:最簡單就是將所有字符加起來,代碼如下:

1
2
3
4
5
6
7
unsigned long HashString(const char *pString, unsigned long tableSize)
{
 unsigned long hashValue = 0;
 while(*pString)
    hashValue += *pString++;
 return hashValue % tableSize;
}

分析:如果字符串的長度有限,而散列表比較大的話,浪費(fèi)比較大。例如,如果字符串最長為16字節(jié),那么用到的僅僅是散列表的前16*127=2032。假如散列表含2729項(xiàng),那么2032以后的項(xiàng)都用不到。

方法2:將上次計(jì)算出來的hash值左移5位(乘以32),再和當(dāng)前關(guān)鍵字相加,能得到較好的均勻分布的效果。

1
2
3
4
5
6
7
unsigned long HashString(const char *pString,unsigned long tableSize)
{
 unsigned long hashValue = 0;
 while (*pString)
 hashValue = (hashValue << 5) + *pString++;
 return hashValue % tableSize;
}

分析:這種方法需要遍歷整個(gè)字符串,如果字符串比較大,效率比較低。

方法3:利用哈夫曼算法,假設(shè)只有0-9這十個(gè)字符組成的字符串,我們借助哈夫曼算法,直接來看實(shí)例: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#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 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<Node*, vector<Node*>, 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(""));
 deleteNodes(root);
}

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多