This commit is contained in:
iheb1196 2020-04-29 11:16:38 +01:00
parent a3c111b5f5
commit c6c6fffac9
2 changed files with 239 additions and 0 deletions

View File

@ -0,0 +1,111 @@
package com.dataStructures;
/**
* This file contains an implementation of an integer only queue which is extremely quick and
* lightweight. In terms of performance it can outperform java.util.ArrayDeque (Java's fastest queue
* implementation) by a factor of 40+! See the benchmark test below for proof. However, the downside
* is you need to know an upper bound on the number of elements that will be inside the queue at any
* given time for this queue to work.
*
*
*/
public class IntQueue {
private int[] ar;
private int front, end, sz;
// maxSize is the maximum number of items
// that can be in the queue at any given time
public IntQueue(int maxSize) {
front = end = 0;
sz = maxSize + 1;
ar = new int[sz];
}
// Return true/false on whether the queue is empty
public boolean isEmpty() {
return front == end;
}
// Return the number of elements inside the queue
public int size() {
if (front > end) return (end + sz - front);
return end - front;
}
public int peek() {
return ar[front];
}
// Add an element to the queue
public void enqueue(int value) {
ar[end] = value;
if (++end == sz) end = 0;
if (end == front) throw new RuntimeException("Queue too small!");
}
// Make sure you check is the queue is not empty before calling dequeue!
public int dequeue() {
int ret_val = ar[front];
if (++front == sz) front = 0;
return ret_val;
}
// Example usage to check the how fast this implementation is
public static void main(String[] args) {
IntQueue q = new IntQueue(5);
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
q.enqueue(4);
q.enqueue(5);
System.out.println(q.dequeue()); // 1
System.out.println(q.dequeue()); // 2
System.out.println(q.dequeue()); // 3
System.out.println(q.dequeue()); // 4
System.out.println(q.isEmpty()); // false
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
System.out.println(q.dequeue()); // 5
System.out.println(q.dequeue()); // 1
System.out.println(q.dequeue()); // 2
System.out.println(q.dequeue()); // 3
System.out.println(q.isEmpty()); // true
benchMarkTest();
}
// BenchMark IntQueue vs ArrayDeque.
private static void benchMarkTest() {
int n = 10000000;
IntQueue intQ = new IntQueue(n);
// IntQueue times at around 0.0324 seconds
long start = System.nanoTime();
for (int i = 0; i < n; i++) intQ.enqueue(i);
for (int i = 0; i < n; i++) intQ.dequeue();
long end = System.nanoTime();
System.out.println("IntQueue Time: " + (end - start) / 1e9);
// ArrayDeque times at around 1.438 seconds
java.util.ArrayDeque<Integer> arrayDeque = new java.util.ArrayDeque<>();
// java.util.ArrayDeque <Integer> arrayDeque = new java.util.ArrayDeque<>(n); // strangely the
// ArrayQueue is slower when you give it an initial capacity.
start = System.nanoTime();
for (int i = 0; i < n; i++) arrayDeque.offer(i);
for (int i = 0; i < n; i++) arrayDeque.poll();
end = System.nanoTime();
System.out.println("ArrayDeque Time: " + (end - start) / 1e9);
}
}

View File

@ -0,0 +1,128 @@
package com.dataStructures;
import static org.junit.Assert.*;
import java.util.*;
import org.junit.Before;
import org.junit.Test;
public class IntQueueTest {
@Before
public void setup() {}
@Test
public void testEmptyQueue() {
IntQueue queue = new IntQueue(0);
assertTrue(queue.isEmpty());
assertEquals(queue.size(), 0);
}
@Test
public void testEnqueueOneElement() {
IntQueue queue = new IntQueue(1);
queue.enqueue(77);
assertEquals(queue.size(), 1);
}
@Test
public void testAll() {
int n = 5;
IntQueue queue = new IntQueue(10);
assertTrue(queue.isEmpty());
for (int i = 1; i <= n; i++) {
queue.enqueue(i);
assertFalse(queue.isEmpty());
}
for (int i = 1; i <= n; i++) {
assertEquals(i, queue.peek());
assertEquals(i, queue.dequeue());
assertEquals(queue.size(), n - i);
}
assertTrue(queue.isEmpty());
n = 8;
for (int i = 1; i <= n; i++) {
queue.enqueue(i);
assertFalse(queue.isEmpty());
}
for (int i = 1; i <= n; i++) {
assertEquals(i, queue.peek());
assertEquals(i, queue.dequeue());
assertEquals(queue.size(), n - i);
}
assertTrue(queue.isEmpty());
n = 9;
for (int i = 1; i <= n; i++) {
queue.enqueue(i);
assertFalse(queue.isEmpty());
}
for (int i = 1; i <= n; i++) {
assertEquals(i, queue.peek());
assertEquals(i, queue.dequeue());
assertEquals(queue.size(), n - i);
}
assertTrue(queue.isEmpty());
n = 10;
for (int i = 1; i <= n; i++) {
queue.enqueue(i);
assertFalse(queue.isEmpty());
}
for (int i = 1; i <= n; i++) {
assertEquals(i, queue.peek());
assertEquals(i, queue.dequeue());
assertEquals(queue.size(), n - i);
}
assertTrue(queue.isEmpty());
}
@Test
public void testPeekOneElement() {
IntQueue queue = new IntQueue(1);
queue.enqueue(77);
assertTrue(queue.peek() == 77);
assertEquals(queue.size(), 1);
}
@Test
public void testDequeueOneElement() {
IntQueue queue = new IntQueue(1);
queue.enqueue(77);
assertTrue(queue.dequeue() == 77);
assertEquals(queue.size(), 0);
}
@Test
public void testRandom() {
for (int qSize = 1; qSize <= 50; qSize++) {
IntQueue intQ = new IntQueue(qSize);
ArrayDeque<Integer> javaQ = new ArrayDeque<>(qSize);
assertEquals(javaQ.isEmpty(), intQ.isEmpty());
assertEquals(javaQ.size(), intQ.size());
for (int operations = 0; operations < 5000; operations++) {
double r = Math.random();
if (r < 0.60) {
int elem = (int) (1000 * Math.random());
if (javaQ.size() < qSize) {
javaQ.offer(elem);
intQ.enqueue(elem);
}
} else {
if (!javaQ.isEmpty()) {
assertEquals((int) javaQ.poll(), (int) intQ.dequeue());
}
}
assertEquals(javaQ.isEmpty(), intQ.isEmpty());
assertEquals(javaQ.size(), intQ.size());
}
}
}
}