Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save XavierGeerinck/10a71183213d38c28d7433d7d3aaf243 to your computer and use it in GitHub Desktop.
Save XavierGeerinck/10a71183213d38c28d7433d7d3aaf243 to your computer and use it in GitHub Desktop.
Algorithms String Encoding HuffmanCode
/**
* @author: Xavier Geerinck
* @title: Huffman encoding
* @subtitle: This algorithm compresses a string it's binary representation
* @method:
* 1. Create a table for each character with their "frequence of occurence"
* 2. Create leaf element of each character and put it in a priority queue (the priority is based on the "frequence of occurence" for that character)
* 3. As long as the queue >= 2 elements
* i. Remove 2 nodes
* ii. Make a new node with the 2 children the 2 removed nodes. This new node has the sum of the priorities. (biggest child left, smallest right).
* iii. Add this new node to the queue
* 4. Once we have this tree we can find the huffman code by searching for our value and if we go left, we write a "0" and if we go right we write a "1"
* @note: performance can be increased by merging some methods (such as textToBinary and createOccurenceTable) but for reading purposes it has been split off.
*/
/**
* A simple node implementation
*/
function Node(key, priority, left, right) {
this._left = left || null;
this._right = right || null;
this._key = key || "";
this._priority = priority || 0;
};
Node.prototype.getLeft = function () {
return this._left;
};
Node.prototype.getRight = function () {
return this._right;
};
Node.prototype.getKey = function () {
return this._key;
};
Node.prototype.getPriority = function () {
return this._priority;
};
Node.prototype.setRight = function (right) {
this._right = right;
};
Node.prototype.setLeft = function (left) {
this._left = left;
};
Node.prototype.setKey = function (key) {
return this._key;
};
Node.prototype.setPriority = function (priority) {
this._priority = priority;
};
/**
* A simple priority queue implementation
*/
function PriorityQueue(comparator) {
this._items = [];
this._comparator = comparator;
};
PriorityQueue.prototype.size = function () {
return this._items.length;
};
PriorityQueue.prototype.isEmpty = function () {
return this.size() == 0;
};
PriorityQueue.prototype.peek = function () {
if (this.isEmpty()) {
throw new Error('PriorityQueue is empty');
}
return this._items[0];
};
PriorityQueue.prototype.dequeue = function () {
var self = this;
var item = this._items[0];
this._items = this._items.slice(1, self.size());
return item;
};
PriorityQueue.prototype.enqueue = function (element) {
var size = this._items.push(element);
var current = size - 1;
while (current > 0) {
//var parent = Math.floor((current - 1) / 2);
var parent = current - 1;
if (this._compare(current, parent) <= 0) break;
this._swap(parent, current);
current = parent;
}
return size;
};
PriorityQueue.prototype.print = function () {
console.log(this._items);
};
PriorityQueue.prototype._compare = function (a, b) {
return this._comparator(this._items[a], this._items[b]);
};
PriorityQueue.prototype._swap = function (a, b) {
var aux = this._items[a];
this._items[a] = this._items[b];
this._items[b] = aux;
};
/**
* Huffman Code Algorith + Utils
*/
function textToBinary(input) {
var result = "";
for (var i = 0; i < input.length; i++) {
result += input[i].charCodeAt(0).toString(2);
}
return result;
}
function createOccurenceTable(input) {
var table = {};
for (var i = 0; i < input.length; i++) {
if (!table[input[i]]) {
table[input[i]] = 1;
} else {
table[input[i]]++;
}
}
return table;
}
function createHuffmanTable(text, huffmanTree) {
var occurenceTable = createOccurenceTable(text);
// TODO
}
function createHuffmanTree(input) {
var occurenceTable = createOccurenceTable(input);
var queue = new PriorityQueue(function (a, b) {
console.log("Comparing: " + a.getPriority() + " to " + b.getPriority());
return a.getPriority() < b.getPriority();
});
// Queue every character
var occurenceTableKeys = Object.keys(occurenceTable);
for (var i = 0; i < occurenceTableKeys.length; i++) {
queue.enqueue(new Node(occurenceTableKeys[i], occurenceTable[occurenceTableKeys[i]]));
}
//queue.print();
// As long as the queue >= 2 elements, continue
while (queue.size() >= 2) {
// Get Items
var itemA = queue.dequeue();
var itemB = queue.dequeue();
// Create node
var newNode = new Node(null, itemA.getPriority() + itemB.getPriority());
// Set largest node left and smallest right
if (itemA.getPriority() > itemB.getPriority) {
newNode.setLeft(itemA);
newNode.setRight(itemB);
} else {
newNode.setLeft(itemB);
newNode.setRight(itemA);
}
// Push on the queue
queue.enqueue(newNode);
}
return queue.peek();
}
var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
var huffmanTree = createHuffmanTree(text);
var huffmanTable = createHuffmanTable(huffmanTree);
var result = "";
for (var i = 0; i < text.length; i++) {
result += huffmanTable[text[i]];
}
document.querySelector("#result").innerHTML = "Normal: <br />" + textToBinary(text) + "<br /><br />Huffman Compressed: <br />" + result;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment