-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCompressor.cpp
More file actions
130 lines (120 loc) · 2.43 KB
/
Copy pathCompressor.cpp
File metadata and controls
130 lines (120 loc) · 2.43 KB
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "Compressor.hpp"
#include <deque>
#include <queue>
#include <iostream>
#include <fstream>
class NodesOrder
{
public:
bool operator()(const Node* a, const Node* b) const
{
return a->getOccurences()>b->getOccurences();
}
};
void Codes::MakeCode(const Node *root, uint32_t prefix, uint8_t len)
{
assert(len<=30);
if(root!=NULL)
{
if(!root->getLabel().empty())
valToCode.insert(Map::value_type(trie.insert(root->getLabel()), prefix));
uint32_t lcode(prefix);
uint32_t rcode(prefix|(1<<len));
MakeCode(root->getLeft(),lcode,len+1);
MakeCode(root->getRight(),rcode,len+1);
}
}
void Codes::inc(const std::string &label)
{
Node *n=new Node(label,0);
auto i=input.insert(n);
if(!i.second)
delete n;
(*i.first)->inc();
}
static size_t countLeaves(const Node *root)
{
if(!root->getLabel().empty())
return 1;
return countLeaves(root->getLeft())+countLeaves(root->getRight());
}
void Codes::compress()
{
std::priority_queue<Node*,std::deque<Node*>,NodesOrder> nodes;
for(auto i:input)
nodes.push(i);
input.clear();
for(;;)
{
assert(!nodes.empty());
Node *l=nodes.top();
nodes.pop();
if(nodes.empty())
{
root=l;
break;
}
Node *r=nodes.top();
nodes.pop();
nodes.push(new Node("",l->getOccurences()+r->getOccurences(),l,r));
}
MakeCode(root, 0);
}
void Codes::load(std::ifstream& f)
{
root=Node::load(f);
MakeCode(root, 0);
delete root;
root=NULL;
trie.compress();
}
void Codes::save(std::ofstream& f) const
{
root->save(f);
}
Node::Node(std::ifstream& f)
{
std::getline(f, label, '\0');
f.read(reinterpret_cast<char*>(&occurences), sizeof(occurences));
char c;
f>>c;
if(c=='1')
left=Node::load(f);
else
left=NULL;
f>>c;
if(c=='1')
right=Node::load(f);
else
right=NULL;
}
void Node::save(std::ofstream& f) const
{
f<<label<<'\0';
f.write(reinterpret_cast<const char*>(&occurences), sizeof(occurences));
if(left)
{
f<<'1';
left->save(f);
}
else
f<<'0';
if(right)
{
f<<'1';
right->save(f);
}
else
f<<'0';
}
#if 0
void dump(const Node *root, const std::string& prefix)
{
if(root!=NULL)
{
std::cout<<prefix<<" "<<root->getLabel()<<"\n";
dump(root->getLeft(), prefix+"0");
dump(root->getRight(), prefix+"1");
}
}
#endif