generated from mhj/guix-configs
Huffman c++
This commit is contained in:
parent
c22ca5e7ab
commit
2cf3e6dd75
|
@ -0,0 +1 @@
|
|||
Code examples, algorithm implementations, and other stuffs.
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue