-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhuffman.h
240 lines (229 loc) · 8.27 KB
/
huffman.h
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#ifndef huffman_h
#define huffman_h
#include "heap.h"
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <queue>
using namespace std;
class HuffmanCode : public map<string,string> {
public:
// --------- HuffmanCode() --------
// default constructor
HuffmanCode() {}
// ---------
// --------- HuffmanCode(istream &) --------
// creates a code from an input stream. The input stream has a line for every
// code association. A line is in the form '<word> <code>'. The code should contain only
// 0s and 1s
// EXCEPT: throws 0 if the stream is not in the proper format (i.e. a line has more than two words, or the second word is not a sequence of 0s and 1s
HuffmanCode(istream &input); //TODO
};
class HuffmanTree {
private:
// ----- TreeNode ------
// A node in the Huffman Tree
struct TreeNode {
// ---------
// links to children. these are nullptr is any of the children is non-existent
TreeNode* children[2];
// ---------
// link to the string representation of the word
string *word;
// ---------
// --------- TreeNode() --------
// default constructor : all links are nullptr
TreeNode() {
children[0] = children[1] = nullptr;
word = nullptr;
}
// ---------
// --------- TreeNode(string) --------
// children are nullptr both, and word is a link to a new string
TreeNode(string s) {
word = new string(s);
children[0] = children[1] = nullptr;
}
// ---------
// --------- TreeNode(string) --------
// children are nullptr taken from the params(could be nullptr) and
// the word is a nullptr
TreeNode(TreeNode *t1, TreeNode *t2) {
word = nullptr;
children[0] = t1;
children[1] = t2;
}
// ---------
// --------- TreeNode(string) --------
// copy constructor
TreeNode(const TreeNode &t) {
if( t.children[0] != nullptr) children[0] = new TreeNode(*t.children[0]);
if( t.children[1] != nullptr) children[1] = new TreeNode(*t.children[1]);
if( t.word != nullptr) word = new string(*t.word);
}
// --------- ~TreeNode() --------
// destructor - deallocates the memory at the node and its descendants
~TreeNode() {
if (word != nullptr) delete word;
if (children[0] != nullptr) delete children[0];
if (children[1] != nullptr) delete children[1];
}
};
// -----
// ----- HuffmanHeap --------
class HuffmanHeap : Heap<TreeNode *> {
public:
// -----
// ----- HuffmanHeap(istream &) --------
// constructor from an input file: a TreeNode is constructed for every node in the input file
// with no children and with priority equal to the frequency of the word in the file
HuffmanHeap(istream &); //TODO
// -----
// ----- pop() --------
// removes the items with the two highest priorities, creates a new TreeNode with these two items as children and no string content, and adds this new Node in the heap with priority equal to the sum of the priorities of the two removed nodes.
// does not do anything if the number of elements is less than 2
void pop(); //TODO
// -----
// ----- lastElement() -----
// returns the top element when the heap has only one element
// EXEPT: throws 1 if the number of elements is not 1
TreeNode* lastElement() {
if (content.size() != 1) throw 1;
return *(content[0]->data);
}
// -----
// ----- hasOneElementLeft() -----
// returns true only if the heap has one element
bool hasOneElementLeft() const {
return (content.size() == 1);
}
};
// -----
TreeNode *root; //the root of the tree
TreeNode *iter; //an iterator that keeps track of a moving position in the tree
// ----
public:
// ----
// ---- HuffmanTree(const HuffmanCode &) -----
// constructor builds a tree that corresponds to the codes given as parameter
// EXCEPT: throws 1 if the code is not a prefix code
// EXCEPT: throws 2 if the codes are not all sequences of 0s and 1s
HuffmanTree(const HuffmanCode &); //TODO
// ----
// ---- HuffmanTree(istream &) -----
// constructor builds a tree from a file containing a block of text. It builds a Huffman Heap
// and pops from it until only one element is left
HuffmanTree(istream &input) {
HuffmanHeap h(input);
while(!h.hasOneElementLeft()) {
h.pop();
}
root = h.lastElement();
iter = root;
}
// ----
// ---- HuffmanTree(const HuffmanTree &) ----
// copy constructor
HuffmanTree(const HuffmanTree &h) {
root = new TreeNode(*h.root);
iter = root;
}
// ----
// ---- resetIterator() ----
// moves iterator back to the root
void resetIterator() {
iter = root;
}
// ----
// ---- moveDownOnZero() ----
// moves iterator down a 0 branch
// EXCEPT: throws 0 if no such branch exists
void moveDownOnZero() {
if (iter->children[0] == nullptr) throw 0;
iter = iter->children[0];
}
// ----
// ---- moveDownOnOne() ----
// moves iterator down a 1 branch
// EXCEPT: throws 1 if no such branch exists
void moveDownOnOne() {
if (iter->children[1] == nullptr) throw 1;
iter = iter->children[1];
}
// ----
// ---- getWordFromIter() ----
// returns a pointer to the string corresponding to
// the iterator
// EXCEPT: throws 2.0 if no such string exists
const string *getWordFromIter() const{
if ( iter->word == nullptr) throw 2.0;
return iter->word;
}
// ----
// ---- dfs(HuffmanCode& hc, TreeNode *tn, string &s) ----
// performs dfs starting at node tn. The string keeps track of the branches one has
// to follow from the root to this node. It adds to hc all leaf nodes
//
void dfs(HuffmanCode& hc, TreeNode *tn, string &s);
// ----
// ---- getCode() ----
// returns a HuffmanCode corersponding to the current HuffmanTree
HuffmanCode getCode() {
HuffmanCode toRet;
string ss("");
dfs(toRet, root, ss);
return toRet;
}
};
class HuffmanDecoder : public HuffmanTree {
private:
// ----
// savedWords keeps track of words that have been decoded every time
// the method push() is called
queue<const string*> savedWords;
// ----
public:
// -------
// ---- HuffmanDecoder(istream &) -----
// overrides constructor of HuffmanTree
HuffmanDecoder(istream &input) : HuffmanTree(input) {}
// -------
// ---- HuffmanDecoder(const HuffmanCode &) -----
// overrides constructor of HuffmanTree
HuffmanDecoder(const HuffmanCode &hc): HuffmanTree(hc) {}
// -------
// ---- push(istream &) ----
//It decodes a sequence of 0s and 1s that is stored in the stream f. All decoded words are
// added to a queue of decoded words, which can be extracted using the method next()
// EXEPT: throws 0 if the sequence has characters other than 0 and 1
// EXEPT: throws 1 if the last word was not fully completed
void push(istream &f); //TODO
// -------
// ---- next() ------
// extracts a single word that were decoded in the method push
// EXEPT: throws 1 if the queue of words is empty
string next() {
if(savedWords.empty()) throw 1;
string toRet = *savedWords.front();
savedWords.pop();
return toRet;
}
};
class HuffmanEncoder {
private:
// ----
// the HuffmanCode used to decode the word
const HuffmanCode &code;
public:
// ----
// ---- HuffmanEncoder(const HuffmanCode &) ---
// constructor that initialized the code used for decoding
HuffmanEncoder(const HuffmanCode &t) : code(t) {}
// ----
// ---- encode(istream &fin, ostream &fout)
// reads content from fin and pushes the corresponding encoding to fout
// EXCEPT: throws 1 if fin contains words that are not in the dictionary of code
void encode(istream &fin, ostream &fout) const; //TODO
};
#endif /* huffman_h */