-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhuffman.cpp
154 lines (129 loc) · 4.23 KB
/
huffman.cpp
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "../headers/huffman.h"
// Huffman Costructor
Huffman::Huffman(string text) {
// Create a Map relating each character found in the text to its respective appearance frequency
unordered_map<char, int> freq = frequencyCount(text);
// Build huffman structure
root = buildHuffman(freq);
encodedString = encodeString(text);
decodedString = decodeString(encodedString);
compressionRatio = computeCompressionRatio(encodedString, decodedString);
}
// This function build a Huffman Tree
Node* Huffman::buildHuffman(unordered_map<char, int> freq){
// build a minheap
MinHeap * minheap = new MinHeap(freq);
int size = freq.size() - 1;
for(int i = 0; i < size; i++){
Node *z = new Node();
z->setLeft(minheap->removeMin());
z->setRight(minheap->removeMin());
int x = z->getLeft()->getFreq();
int y = z->getRight()->getFreq();
z->setFreq(x+y);
minheap->insert(z);
}
Node *aux = minheap->removeMin();
// Call destructor of MinHeap because the Huffman structure always been created
minheap->~MinHeap();
return aux;
}
// This function encode the string using the Huffman table
string Huffman::encodeString(string initialString){
// Create Huffman table
unordered_map<char, string> huffmanTable;
createHuffmanTable(root, "", huffmanTable);
// Encode string
string encodedText = "";
for (char character: initialString) {
encodedText = encodedText + huffmanTable[character];
}
return encodedText;
}
// Decode string function
string Huffman::decodeString(string encodedString) {
string decodedString = "";
Node* aux = root;
int size = (int) encodedString.size() + 1;
for(int i = 0; i < size; i++){
if (isLeaf(aux)){
decodedString = decodedString + aux->getInfo();
aux = root;
}
if (encodedString[i] =='0'){
aux = aux->getLeft();
} else {
aux = aux->getRight();
}
}
return decodedString;
}
/*
* This function create the Huffman table.
* To encode string is necessary, given the constructed huffman tree, to know to each character
* which will be your encoding in bits. This is done traversing the Huffman tree in preorder and
* considering that the left child of each Node is represented by "0" and the right child by "1".
* As a result everything is stored in a Map structure, where the key is a character and the value
* are the bit sequence that represents this.
*/
void Huffman::createHuffmanTable(Node* node, string aux, unordered_map<char, string> &huffmanTable) {
// recursion base case
if (node == 0){
return;
}
// if the current Node is a leaf
if (isLeaf(node)) {
huffmanTable[node->getInfo()] = aux;
}
createHuffmanTable(node->getLeft(), aux + "0", huffmanTable);
createHuffmanTable(node->getRight(), aux + "1", huffmanTable);
}
/*
* This function count each character occurrence in text and store data
* in Map structure where the pair key:value are represented by character:occurence
*/
unordered_map<char, int> Huffman::frequencyCount(string text){
string aux = text;
unordered_map<char, int> freq;
for (char character: aux) {
freq[character] = freq[character] + 1;
}
return freq;
}
// Check if a Node is a leaf
bool Huffman::isLeaf(Node* node) {
if(node->getLeft() == 0 && node->getRight() == 0){
return true;
}
return false;
}
// This functions compute the compression ratio.
float Huffman::computeCompressionRatio(string encodedString, string decodedString){
float encodedSize = encodedString.size();
float decodedSize = decodedString.size();
float ratio = (float) encodedSize/(decodedSize * 8) * 100;
float percentRatio = -ratio + 100;
return percentRatio;
}
// Huffman Destructor
Huffman::~Huffman(){
deleteHuffman(root);
}
// Desctruc the Huffman structure
void Huffman::deleteHuffman(Node* node) {
if(node != 0){
deleteHuffman(node->getLeft());
deleteHuffman(node->getRight());
delete node;
}
}
// Getters functions
string Huffman::getEncodedString(){
return encodedString;
}
string Huffman::getDecodedString(){
return decodedString;
}
float Huffman::getCompressionRatio(){
return compressionRatio;
}