-
Notifications
You must be signed in to change notification settings - Fork 0
/
HCTree.cpp
132 lines (115 loc) · 2.7 KB
/
HCTree.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
#include <algorithm>
#include <bitset>
#include "HCTree.hpp"
//Default destructor for the tree
HCTree::~HCTree()
{
delete root;
}
//Method that gets the value or code and puts it into a sequence of type string
std::string HCTree::getValue(byte bits) const
{
//Checks and returns a valid sequence of bits
if(value[bits].size())
{
return value[bits];
}
HCNode* node = leaves[bits];
std::string seq;
//This will traverse the tree up to the root while setting the seqence
while( node->p )
{
if (node->p->c0 && node == node->p->c0)
{
seq = "0" + seq;
}
else
{
seq = "1" + seq;
}
node = node->p;
}
return seq;
}
//Method to build the Huffman Code Tree
void HCTree::build(const std::vector<int> &freqs)
{
//Starts by adding the correct leaves into the given priority queue
for(size_t index = 0; index < freqs.size(); index++)
{
//Checks to make sure there is a current freq at this point
if(freqs[index])
{
//Creates the node and pushes it to the queue.
HCNode *node = new HCNode(freqs[index], index);
leaves[index] = node;
queue.push(node);
}
}
if(queue.size() == 0)
{
HCNode *rootNode = new HCNode(0,0);
root = rootNode;
return;
}
//Adds a new node if the queue is only of size 1
if(queue.size() == 1)
{
queue.push(new HCNode(0, 0));
}
//Constructs the internal nodes of the Huffman tree.
HCNode *node;
while (queue.size() > 1)
{
node = new HCNode(0, 0);
node->c0 = queue.top();
node->c0->p = node;
queue.pop();
node->c1 = queue.top();
node->c1->p = node;
queue.pop();
node->count = node->count + node->c0->count;
node->count = node->count + node->c1->count;
queue.push(node);
}
//Changes the root of the tree when it is full constructed.
root = queue.top();
}
//Method that encodes the tree into an out file to be decoded later on
void HCTree::encode(byte symbol, BitOutputStream& out) const
{
//Gets the certain code sequence of the current symbol
std::string seq = getValue(symbol);
//Writes the bits to the correct sequences
for(size_t index = 0; index < seq.size(); index++)
{
if(seq[index] == '1')
{
out.writeBit(true);
}
else
{
out.writeBit(false);
}
}
}
//Method that reads in a compress file and decodes it to it's original form
int HCTree::decode(BitInputStream& in) const
{
HCNode *currNode = root;
int bit;
//Traverses the tree to each node and returns the respective symbol
while(currNode->c0 || currNode->c1)
{
bit = in.readBit();
if(bit == 1)
{
currNode = currNode->c1;
}
else
{
currNode = currNode->c0;
}
}
return currNode->symbol;
}