Huffman c++

This commit is contained in:
Jaime Lopez 2021-12-09 22:48:24 -05:00
parent c22ca5e7ab
commit 2cf3e6dd75
4 changed files with 132 additions and 145 deletions

3
README
View File

@ -1,3 +0,0 @@
# C/C++ Examples
My collection of C-implementations

1
README.md Normal file
View File

@ -0,0 +1 @@
Code examples, algorithm implementations, and other stuffs.

View File

@ -1,5 +1,6 @@
#include <cstdlib>
#include <cstring>
#include <cstdint> // char
#include <iostream>
#include <memory>
@ -7,160 +8,149 @@
using namespace std;
class Node;
typedef shared_ptr<Node> ptrNode;
const int array_size = 256;
struct Node {
char symb;
int freq;
Node *left;
Node *right;
Node(char symb, int freq)
: symb(symb), freq(freq), left(nullptr), right(nullptr) {
}
Node(Node *nd) // Just copy the content, not thep pointers
: symb(nd->symb), freq(nd->freq), left(nullptr), right(nullptr) {
class Node {
public:
Node(char symbol, unsigned freq) : symbol_(symbol), freq_(freq), left_(nullptr), right_(nullptr) {}
Node(ptrNode nd) :
symbol_(nd->getSymbol()),
freq_(nd->getFreq()),
left_(nd->getLeft()),
right_(nd->getRight()) {}
Node (ptrNode a, ptrNode b) {
symbol_ = 0;
freq_ = a->freq_ + b->freq_;
if (a->freq_ < b->freq_) {
left_ = a; right_ = b;
}
else {
left_ = b; right_ = a;
}
cout << "Virtual node: " << left_->getSymbol() << ' ' << right_->getSymbol() << ' ' << freq_ << endl;
}
char getSymbol() { return symbol_; }
unsigned getFreq() { return freq_; }
ptrNode getLeft() { return left_; }
ptrNode getRight() { return right_; }
void setLeft(ptrNode nd) { left_ = nd; }
void setRight(ptrNode nd) { right_ = nd; }
private:
char symbol_;
unsigned freq_;
ptrNode left_;
ptrNode right_;
Node(Node& a, Node& b) {
symb = 0;
freq = a.freq + b.freq;
if (a.freq > b.freq) {
left = &a; right = &b;
} else if (a.freq < b.freq) {
left = &b; right = &a;
} else if (a.symb < b.symb) { // They have the same frequency
left = &a; right = &b; // So, order by symbol
} else {
left = &b;
right = &a;
}
}
};
class Queue;
struct Queue;
class Tree {
public:
Tree(Queue& q);
Tree(string s) {
unsigned i;
unsigned len = 256;
char symbols[len];
unsigned freqs[len];
for (i = 0; i < len; i++)
freqs[i] = 0;
for (i = 0; i < s.size(); i++) {
unsigned index = static_cast<unsigned>(s.at(i));
freqs[index]++;
symbols[index] = s.at(i);
}
for (i = 0; i < len; i++)
if (freqs[i] > 0) {
insert(symbols[i], freqs[i]);
// cout << symbols[i] << ' ' << freqs[i] << endl;
}
struct Tree {
Node *root;
Tree(Queue q);
Tree(string s) : root(nullptr) {
const int n = array_size;
int freqs[n];
for (int i = 0; i < n; i++)
freqs[i] = 0;
for (size_t i = 0; i < s.size(); i++) {
// cout << s[i] << ' ' << int(s[i]) << endl;
freqs[int(s[i])]++;
}
ptrNode getRoot() { return root_; }
unsigned getSize() { return size_; }
void insert(char symbol, unsigned freq) {
ptrNode curr = nullptr;
ptrNode prev = root_;
auto nd = make_shared<Node>(symbol, freq);
size_++;
if (root_ == nullptr) {
root_ = nd;
return;
for (int i = 0; i < n; i++)
if (freqs[i] > 0) {
// cout << char(i) << ' ' << i << endl;
insert(new Node(char(i), freqs[i]));
}
while (true) {
if (prev->getFreq() > nd->getFreq()) {
curr = prev->getLeft();
if (curr == nullptr) {
prev->setLeft(nd);
break;
}
}
else {
curr = prev->getRight();
if (curr == nullptr) {
prev->setRight(nd);
break;
}
}
prev = curr;
}
~Tree() {
free(root);
}
void free(Node *nd) {
if (!nd)
return;
if (nd->left) free(nd->left);
if (nd->right) free(nd->right);
delete nd;
}
void insert(Node *nd) {
Node *curr = root;
if (!root) {
root = nd;
return;
}
for (bool inserted = false; !inserted; ) {
if (nd->freq < curr->freq) {
if (!curr->left) {
curr->left = nd;
inserted = true;
} else
curr = curr->left;
} else {
if (!curr->right) {
curr->right = nd;
inserted = true;
} else
curr= curr->right;
}
}
private:
ptrNode root_;
unsigned size_;
}
};
class Queue {
public:
Queue(Tree t) {
size_ = 0;
data_ = new ptrNode[(t.getSize())];
extract(t.getRoot());
/*
for (unsigned i = 0; i < size_; i++) {
cout << data_[i]->getSymbol() << ' ' << data_[i]->getFreq() << endl;
}
*/
}
~Queue() {
delete[] data_;
}
ptrNode getNode(unsigned i) { return data_[i]; }
unsigned getSize() { return size_; }
private:
void extract(ptrNode nd) {
if (nd->getLeft())
extract(nd->getLeft());
data_[size_++] = nd;
if (nd->getRight())
extract(nd->getRight());
}
ptrNode *data_;
unsigned size_;
struct Queue {
int size;
Node *queue[array_size];
Queue(Tree *t) : size(0) {
extract(t->root);
}
void extract(Node *nd) {
if (nd->left)
extract(nd->left);
queue[size++] = nd;
if (nd->right)
extract(nd->right);
}
};
Tree::Tree(Queue& q) {
ptrNode a, b, c, d;
size_ = 0;
unsigned i = 0;
while (true) {
a = ptrNode(new Node(q.getNode(i++)));
if (i == q.getSize()) {
root_ = ptrNode(new Node(a, root_));
Tree::Tree(Queue q) : root(nullptr) {
Node *a, *b, *c;
for (int i = 0; i < q.size; ) {
a = new Node(q.queue[i++]);
if (i== q.size) {
if (root)
root = new Node(*a, *root);
else
root = a;
break;
}
b = ptrNode(new Node(q.getNode(i++)));
c = ptrNode(new Node(a, b));
if (root_ != nullptr)
root_ = ptrNode(new Node(c, root_));
b = new Node(q.queue[i++]);
c = new Node(*a, *b);
if (root)
root = new Node(*c, *root);
else
root_ = c;
root = c;
}
}
void huffmanNode(ptrNode nd, string sa) {
if (nd->getLeft())
huffmanNode(nd->getLeft(), sa + '0');
if (nd->getSymbol() != 0)
cout << nd->getSymbol() << ' ' << nd->getFreq() << ' ' << sa << endl;
if (nd->getRight())
huffmanNode(nd->getRight(), sa + '1');
void huff_code(Node *nd, string s) {
if (nd->left)
huff_code(nd->left, s + '0');
if (!nd->left && !nd->right)
cout << nd->symb << ' ' << nd->freq << ' ' << s << endl;
if (nd->right)
huff_code(nd->right, s + '1');
}
void huffman(string s) {
Tree tree(s);
Queue queue(tree);
Tree huff(queue);
huffmanNode(huff.getRoot(), "");
Tree t(s);
Queue q(&t);
Tree h(q);
huff_code(h.root, "");
}
int main() {
@ -168,4 +158,3 @@ int main() {
huffman(s);
return 0;
}

View File

@ -37,13 +37,14 @@ node_t *node_new(char symbol, unsigned freq) {
}
void node_link(node_t *nd, node_t *a, node_t *b) {
if (a->freq < b->freq) {
nd->left = a;
nd->right = b;
}
else {
nd->left = b;
nd->right = a;
if (a->freq > b->freq) {
nd->left = a; nd->right = b;
} else if (a->freq < b->freq) {
nd->left = b; nd->right = a;
} else if (a->symbol < b->symbol) {
nd->left = a; nd->right = b;
} else {
nd->left = b; nd->right = a;
}
}
@ -221,8 +222,7 @@ char *read_from_stream() {
}
int main() {
char *s = read_from_stream();
char *s = "ACCEBFFFFAAXXBLKE";
huffman(s);
free(s);
return 0;
}