Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
/decoded.txt
/src/decoded.txt
/.DS_Store
/src/lib/
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ Average Time: 1291.0

It is found that 4-ary heap is the fastest. So later encoding is done using 4-ary heap.

* encoder.java: Produces code_table.txt containing codes for all the unique messages; and encoded.bin, which is the binary file for the codes corresponding to the input file.
* Encoder.java: Produces code_table.txt containing codes for all the unique messages; and encoded.bin, which is the binary file for the codes corresponding to the input file.

Usage:
```
~:src$ java encoder ../sample_input_large.txt
~:src$ java Encoder ../sample_input_large.txt
Reading input file ...
Building Freq Table ...
Building huffman tree... Done.
Expand All @@ -39,11 +39,11 @@ Generating encoded.bin .. Done.

As a proof of concept, we will reconstruct our input using code_table.txt and encoded.bin

* decoder.java: Takes in input encoded.bin and code_table.txt and produces decoded.txt which is exactly the same as sample_input_large.txt as used in encoder.
* Decoder.java: Takes in input encoded.bin and code_table.txt and produces decoded.txt which is exactly the same as sample_input_large.txt as used in Encoder.

Usage:
```
~:src$ java decoder encoded.bin code_table.txt
~:src$ java Decoder encoded.bin code_table.txt
Building huffman tree from code_table.txt ..
Reading code_table.txt .. Done.
Reading encoded.bin .. Done.
Expand Down
70 changes: 35 additions & 35 deletions src/BinaryHeap.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
class BinaryHeap {

private Node[] data;
public int heap_size;

public void stub(){
System.out.println("Reached stub func");
}
private int heap_size;

/** Constructor **/
public BinaryHeap(int num_nodes){
data = new Node[num_nodes];
heap_size = 0;
}

public int getSize() { return heap_size; }

public boolean is_empty() {
return (heap_size == 0);
Expand Down Expand Up @@ -46,8 +44,7 @@ public Node del_min(){
if (is_empty())
return null;
else{
Node min_node = new Node(0,-1);
min_node = data[0];
Node min_node = data[0];
data[0] = data[heap_size-1];
heap_size--;
if (heap_size>0)
Expand All @@ -57,41 +54,44 @@ public Node del_min(){
}

private void manage_heap_upwards(int node_index){
int parent_index;
Node temp = new Node(0,-1);
if (node_index!=0){
parent_index = get_parent_index(node_index);
if (data[parent_index].get_freq() >= data[node_index].get_freq()){
temp = data[parent_index];
while (node_index != 0) {
int parent_index = get_parent_index(node_index);
if (data[parent_index].get_freq() > data[node_index].get_freq()){
Node temp = data[parent_index];
data[parent_index] = data[node_index];
data[node_index] = temp;
manage_heap_upwards(parent_index);
node_index = parent_index;
} else {
break;
}
}
}

private void manage_heap_downwards(int node_index){
int l_index,r_index,min_index;
Node temp = new Node(0,-1);
l_index = get_left_child_index(node_index);
r_index = get_right_child_index(node_index);
if (r_index>=heap_size){
if (l_index>=heap_size)
return;
else
min_index = l_index;
}
else {
if (data[l_index].get_freq() <= data[r_index].get_freq())
min_index = l_index;
else
min_index = r_index;
}
if (data[node_index].get_freq() > data[min_index].get_freq()){
temp = data[min_index];
data[min_index] = data[node_index];
data[node_index] = temp;
manage_heap_downwards(min_index);
while (true) {
int l_index = get_left_child_index(node_index);
int r_index = get_right_child_index(node_index);
int min_index;
if (r_index>=heap_size){
if (l_index>=heap_size)
break;
else
min_index = l_index;
}
else {
if (data[l_index].get_freq() <= data[r_index].get_freq())
min_index = l_index;
else
min_index = r_index;
}
if (data[node_index].get_freq() > data[min_index].get_freq()){
Node temp = data[min_index];
data[min_index] = data[node_index];
data[node_index] = temp;
node_index = min_index;
} else {
break;
}
}
}

Expand Down
107 changes: 107 additions & 0 deletions src/BinaryHeapTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

class BinaryHeapTest {

@Test
void testInsertAndDelMin() {
BinaryHeap heap = new BinaryHeap(10);
int[] freqs = {5, 3, 8, 1, 4};
for (int f : freqs) {
heap.insert(new Node(f, f));
}
int[] expected = {1, 3, 4, 5, 8};
for (int e : expected) {
Node n = heap.del_min();
assertNotNull(n);
assertEquals(e, n.get_freq());
}
}

@Test
void testIsEmpty() {
BinaryHeap heap = new BinaryHeap(10);
assertTrue(heap.is_empty());
heap.insert(new Node(5, 0));
assertFalse(heap.is_empty());
heap.del_min();
assertTrue(heap.is_empty());
}

@Test
void testSingleElement() {
BinaryHeap heap = new BinaryHeap(10);
heap.insert(new Node(42, 0));
assertFalse(heap.is_empty());
Node n = heap.del_min();
assertNotNull(n);
assertEquals(42, n.get_freq());
assertTrue(heap.is_empty());
}

@Test
void testEqualFrequencies() {
BinaryHeap heap = new BinaryHeap(10);
heap.insert(new Node(7, 0));
heap.insert(new Node(7, 1));
heap.insert(new Node(7, 2));
List<Integer> msgs = new ArrayList<>();
while (!heap.is_empty()) {
Node n = heap.del_min();
assertNotNull(n);
assertEquals(7, n.get_freq());
msgs.add(n.get_msg());
}
assertEquals(3, msgs.size());
Collections.sort(msgs);
assertEquals(List.of(0, 1, 2), msgs);
}

@Test
void testGetRoot() {
BinaryHeap heap = new BinaryHeap(10);
heap.insert(new Node(5, 0));
heap.insert(new Node(3, 1));
heap.insert(new Node(8, 2));
Node root = heap.get_root();
assertNotNull(root);
assertEquals(3, root.get_freq());
// get_root should not remove the element
assertEquals(3, heap.getSize());
}

@Test
void testDelMinOnEmpty() {
BinaryHeap heap = new BinaryHeap(10);
assertNull(heap.del_min());
}

@Test
void testGetRootOnEmpty() {
BinaryHeap heap = new BinaryHeap(10);
assertNull(heap.get_root());
}

@Test
void testManyElements() {
Random rng = new Random(12345);
int n = 100;
BinaryHeap heap = new BinaryHeap(n);
for (int i = 0; i < n; i++) {
heap.insert(new Node(rng.nextInt(10000), i));
}
int prev = -1;
for (int i = 0; i < n; i++) {
Node node = heap.del_min();
assertNotNull(node);
assertTrue(node.get_freq() >= prev, "Extraction order must be non-decreasing");
prev = node.get_freq();
}
assertTrue(heap.is_empty());
}
}
39 changes: 18 additions & 21 deletions src/D_aryHeap.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
class D_aryHeap {

public void stub(){
System.out.println("Reached stub func");
}

private Node[] data;
private int d;
public int heap_size;
private int heap_size;

/** Constructor **/
public D_aryHeap(int num_nodes, int d){
this.data = new Node[num_nodes+3];
this.d = d;
this.heap_size = 3;
}

public int getSize() { return heap_size; }

public boolean is_empty() {
return (heap_size == 3);
Expand All @@ -40,8 +38,7 @@ public Node del_min(){
if (is_empty())
return null;
else{
Node min_node = new Node(0,-1);
min_node = data[3];
Node min_node = data[3];
data[3] = data[heap_size-1];
heap_size--;
if (heap_size>3)
Expand All @@ -51,29 +48,29 @@ public Node del_min(){
}

private void manage_heap_upwards(int node_index) {
int parent_index;
Node temp = new Node(0,-1);
if (node_index!=3){
parent_index = get_parent_index(node_index);
if (data[parent_index].get_freq() >= data[node_index].get_freq()){
temp = data[parent_index];
while (node_index != 3) {
int parent_index = get_parent_index(node_index);
if (data[parent_index].get_freq() > data[node_index].get_freq()){
Node temp = data[parent_index];
data[parent_index] = data[node_index];
data[node_index] = temp;
manage_heap_upwards(parent_index);
node_index = parent_index;
} else {
break;
}
}
}

private void manage_heap_downwards(int node_index){
Node temp = new Node(0,-1);
int min_index;
if (get_k_child_index(node_index, 1)<heap_size){
min_index = get_min_child_index(node_index);
if (data[node_index].get_freq() >= data[min_index].get_freq()){
temp = data[min_index];
while (get_k_child_index(node_index, 1) < heap_size) {
int min_index = get_min_child_index(node_index);
if (data[node_index].get_freq() > data[min_index].get_freq()){
Node temp = data[min_index];
data[min_index] = data[node_index];
data[node_index] = temp;
manage_heap_downwards(min_index);
node_index = min_index;
} else {
break;
}
}
}
Expand Down
Loading