In: Computer Science
Starting with the SkiplistListclass, implement a FastDefaultListclass that represents an infinite list with indices 0,1,2,3,...,∞.When we start, every value in this list is assigned the default value null. Otherwise, this class behaves just like a List; it has the add(i,x), remove(i), set(i,x), and get(i)that behave just like the same methods in a list. Each of these operations should run in O(log n)time. The size()method is already implemented for you, it returns the largest value you can store in an int.A DumbDefaultListclass has already been implemented for you. You can use it to help test the correctness of your implementation.Your FastDefaultListshould have the same output for a given input as DumbDefaultList, but it should run much faster.Warning: This is not a hack job. First understand how the SkiplistListclass works and figure out how you can modify it to do what this question asks.Hint: Work slowly. There is not much code you have to change in the FastDefaultList.javafile (which is mostly just a copy of SkiplistList), but it is delicate. Checkpoint your work often and test carefully as you go.;
package comp2402a3;
import java.lang.reflect.Array;
import java.lang.IllegalStateException;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
/**
* Implements the List interface as a skiplist so that all the
* standard operations take O(log n) time
*
* TODO: Modify this so that it creates a DefaultList, which is
basically
* an infinitely long list whose values start out as null
*
*/
public class FastDefaultList<T> extends AbstractList<T>
{
class Node {
T x;
Node[] next;
int[] length;
@SuppressWarnings("unchecked")
public Node(T ix, int h) {
x = ix;
next = (Node[])Array.newInstance(Node.class, h+1);
length = new int[h+1];
}
public int height() {
return next.length - 1;
}
}
/**
* This node sits on the left side of the skiplist
*/
protected Node sentinel;
/**
* The maximum height of any element
*/
int h;
/**
* The number of elements stored in the skiplist
*/
int n; // Hint: You don't need this anymore!
/**
* A source of random numbers
*/
Random rand;
public FastDefaultList() {
n = 0;
sentinel = new Node(null, 32);
h = 0;
rand = new Random(0);
}
/**
* Represents a node/index Pair
*/
protected class Pair {
Node u;
int i;
Pair(Node u, int i) {
this.u = u;
this.i = i;
}
}
/**
* Find the node that precedes list index i in the skiplist.
*
* @param x - the value to search for
* @return the predecessor of the node at index i or the final
* node if i exceeds size() - 1.
*/
protected Node findPred(int i) {
// Hint: It's not enough to know u, you also need the value
j,
// maybe change the return type to Pair and return the pair
(u,j)
Node u = sentinel;
int r = h;
int j = -1; // index of the current node in list 0
while (r >= 0) {
while (u.next[r] != null && j + u.length[r] < i) {
j += u.length[r];
u = u.next[r];
}
r--;
}
return u;
}
public T get(int i) {
// Hint: this is too restrictive any non-negative i is
allowed
if (i < 0 || i > n-1) throw new
IndexOutOfBoundsException();
// Hint: Are you sure findPred(i).next is the node you're looking
for?
return findPred(i).next[0].x;
}
public T set(int i, T x) {
// Hint: this is too restrictive any non-negative i is
allowed
if (i < 0 || i > n-1) throw new
IndexOutOfBoundsException();
// Hint: Are you sure findPred(i).next is the node you're looking
for?
// If it's not, you'd better add a new node, maybe get
everything
// else working and come back to this later.
Node u = findPred(i).next[0];
T y = u.x;
u.x = x;
return y;
}
/**
* Insert a new node into the skiplist
* @param i the index of the new node
* @param w the node to insert
* @return the node u that precedes v in the skiplist
*/
protected Node add(int i, Node w) {
Node u = sentinel;
int k = w.height();
int r = h;
int j = -1; // index of u
while (r >= 0) {
while (u.next[r] != null && j+u.length[r] < i) {
j += u.length[r];
u = u.next[r];
}
u.length[r]++; // accounts for new node in list 0
if (r <= k) {
w.next[r] = u.next[r];
u.next[r] = w;
w.length[r] = u.length[r] - (i - j);
u.length[r] = i - j;
}
r--;
}
n++;
return u;
}
/**
* Simulate repeatedly tossing a coin until it comes up tails.
* Note, this code will never generate a height greater than
32
* @return the number of coin tosses - 1
*/
protected int pickHeight() {
int z = rand.nextInt();
int k = 0;
int m = 1;
while ((z & m) != 0) {
k++;
m <<= 1;
}
return k;
}
public void add(int i, T x) {
// Hint: bounds checking again!
if (i < 0 || i > n) throw new
IndexOutOfBoundsException();
Node w = new Node(x, pickHeight());
if (w.height() > h)
h = w.height();
add(i, w);
}
public T remove(int i) {
// Hint: bounds checking again!
if (i < 0 || i > n-1) throw new
IndexOutOfBoundsException();
T x = null;
Node u = sentinel;
int r = h;
int j = -1; // index of node u
while (r >= 0) {
while (u.next[r] != null && j+u.length[r] < i) {
j += u.length[r];
u = u.next[r];
}
u.length[r]--; // for the node we are removing
if (j + u.length[r] + 1 == i && u.next[r] != null) {
x = u.next[r].x;
u.length[r] += u.next[r].length[r];
u.next[r] = u.next[r].next[r];
if (u == sentinel && u.next[r] == null)
h--;
}
r--;
}
n--;
return x;
}
public int size() {
return Integer.MAX_VALUE;
}
public String toString() {
// This is just here to help you a bit with debugging
StringBuilder sb = new StringBuilder();
int i = -1;
Node u = sentinel;
while (u.next[0] != null) {
i += u.length[0];
u = u.next[0];
sb.append(" " + i + "=>" + u.x);
}
return sb.toString();
}
public static void main(String[] args) {
// put your test code here if you like
}
}
import java.util.List;
import java.util.AbstractList;
import java.util.Map;
import java.util.HashMap;
public class DumbDefaultList<T> extends
AbstractList<T> {
Map<Integer,T> map;
public DumbDefaultList() {
map = new HashMap<Integer,T>();
}
public int size() {
return Integer.MAX_VALUE;
}
public T get(int i) {
return map.get(i);
}
public T set(int i, T x) {
return map.put(i, x);
}
public void add(int i, T x) {
Map<Integer, T> map2 = new HashMap<Integer,T>();
for (Integer k : map.keySet()) {
if (k >= i) {
map2.put(k, map.get(k));
}
}
for (Integer k : map2.keySet()) {
map.remove(k);
}
for (Map.Entry<Integer,T> e : map2.entrySet()) {
map.put(e.getKey()+1, e.getValue());
}
map.put(i, x);
}
public T remove(int i) {
Map<Integer, T> map2 = new HashMap<Integer,T>();
for (Integer k : map.keySet()) {
if (k >= i) {
map2.put(k, map.get(k));
}
}
for (Integer k : map2.keySet()) {
map.remove(k);
}
T retval = map2.remove(i);
for (Map.Entry<Integer,T> e : map2.entrySet()) {
map.put(e.getKey()-1, e.getValue());
}
return retval;
}
}
Working code implemented in Java and comments for better understanding:
Here I am attaching 6 files:
Code for A2Table.java
package comp2402a3;
import java.util.List;
import java.util.ArrayList;
public class A2Table<T> implements Table<T> {
List<List<T>> tab;
int nrows, ncols;
public A2Table(Class<T> t) {
nrows = 0;
ncols = 0;
tab = new
ArrayList<List<T>>();
}
public int rows() {
return nrows;
}
public int cols() {
return ncols;
}
public T get(int i, int j) {
if (i < 0 || i > rows() - 1
|| j < 0 || j > cols()-1)
throw new
IndexOutOfBoundsException();
return tab.get(i).get(j);
}
public T set(int i, int j, T x) {
if (i < 0 || i > rows() - 1
|| j < 0 || j > cols()-1)
throw new
IndexOutOfBoundsException();
return tab.get(i).set(j, x);
}
public void addRow(int i) {
if (i < 0 || i > rows())
throw new IndexOutOfBoundsException();
nrows++;
List<T> row = new
ArrayList<T>();
for (int j = 0; j < cols(); j++)
row.add(null);
tab.add(i, row);
}
public void removeRow(int i) {
if (i < 0 || i > rows() - 1)
throw new IndexOutOfBoundsException();
nrows--;
tab.remove(i);
}
public void addCol(int j) {
if (j < 0 || j > cols())
throw new IndexOutOfBoundsException();
ncols++;
for (int i = 0; i < rows();
i++)
tab.get(i).add(j, null);
}
public void removeCol(int j) {
if (j < 0 || j > cols() - 1)
throw new IndexOutOfBoundsException();
ncols--;
for (int i = 0; i < rows();
i++)
tab.get(i).remove(j);
}
public String toString() {
StringBuilder sb = new
StringBuilder();
for (int i = 0; i < rows(); i++)
{
for (int j = 0;
j < cols(); j++) {
sb.append(String.valueOf(get(i, j)));
sb.append(" ");
}
sb.append("\n");
}
return sb.toString();
}
public static void main(String[] args) {
Tester.testTable(new
A2Table<Integer>(Integer.class));
}
}
Code Screenshots:
Code for DumbDefaultList.java
package comp2402a3;
import java.util.List;
import java.util.AbstractList;
import java.util.Map;
import java.util.HashMap;
public class DumbDefaultList<T> extends
AbstractList<T> {
Map<Integer,T> map;
public DumbDefaultList() {
map = new HashMap<Integer,T>();
}
public int size() {
return Integer.MAX_VALUE;
}
public T get(int i) {
return map.get(i);
}
public T set(int i, T x) {
return map.put(i, x);
}
public void add(int i, T x) {
Map<Integer, T> map2 = new HashMap<Integer,T>();
for (Integer k : map.keySet()) {
if (k >= i) {
map2.put(k, map.get(k));
}
}
for (Integer k : map2.keySet()) {
map.remove(k);
}
for (Map.Entry<Integer,T> e : map2.entrySet()) {
map.put(e.getKey()+1, e.getValue());
}
map.put(i, x);
}
public T remove(int i) {
Map<Integer, T> map2 = new HashMap<Integer,T>();
for (Integer k : map.keySet()) {
if (k >= i) {
map2.put(k, map.get(k));
}
}
for (Integer k : map2.keySet()) {
map.remove(k);
}
T retval = map2.remove(i);
for (Map.Entry<Integer,T> e : map2.entrySet()) {
map.put(e.getKey()-1, e.getValue());
}
return retval;
}
public static void main(String[] args) {
Tester.testDefaultList(new DumbDefaultList<Integer>());
}
}
Code Screenshots:
Code for FastDefaultList.java
package comp2402a3;
import java.lang.reflect.Array;
import java.lang.IllegalStateException;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
/**
* Implements the List interface as a skiplist so that all the
* standard operations take O(log n) time
*
* TODO: Modify this so that it creates a DefaultList, which is
basically
* an infinitely long list whose values start out as null
*
*/
public class FastDefaultList<T> extends AbstractList<T>
{
class Node {
T x;
Node[] next;
int[] length;
int j; //index of current
node
@SuppressWarnings("unchecked")
public Node(T ix, int h, int j)
{
x = ix;
next =
(Node[])Array.newInstance(Node.class, h+1);
length = new
int[h+1];
this.j =
j;
}
public int height() {
return
next.length - 1;
}
/*
public int getJ() {
return
this.j;
}
*/
//in the case that j must be
changed in the future
public void setJ(int i) {
this.j =
i;
}
}
/**
* This node sits on the left side of the
skiplist
*/
protected Node sentinel;
/**
* The maximum height of any element
*/
int h;
/**
* A source of random numbers
*/
Random rand;
public FastDefaultList() {
sentinel = new Node(null, 32,
0);
h = 0;
rand = new Random(0);
}
/**
* Find the node that precedes list index i in the
skiplist.
*
* @param x - the value to search for
* @return the predecessor of the node at index i or
the final
* node if i exceeds size() - 1.
*/
protected Node findPred(int i) {
Node u = sentinel;
int r = h;
int j = -1; // index of the current
node in list 0
while (r >= 0) {
while (u.next[r]
!= null && j + u.length[r] < i) {
j += u.length[r];
u = u.next[r];
}
r--;
}
return u; //now returns u and j
(index)
}
public T get(int i) {
// Hint: this is too restrictive any non-negative i is
allowed
//if (i < 0 || i > n-1) throw
new IndexOutOfBoundsException();
if (i > size()-1 || i < 0)
throw new IndexOutOfBoundsException(); //can't have a negative
index
Node z = findPred(i);
if (z.next[0] != null) {
if (z.next[0].j
== i) {
return z.next[0].x; //found it
}
}
return null;
}
public T set(int i, T x) {
// Hint: this is too restrictive any non-negative i is
allowed
//if (i < 0 || i > n-1) throw
new IndexOutOfBoundsException();
if (i > size()-1 || i < 0)
throw new IndexOutOfBoundsException(); //can't have a negative
index
Node z = findPred(i); T
replace = null;
if (z.next[0] != null) {
if (z.next[0].j
== i) {
replace = z.next[0].x;
z.next[0].x = x;
return replace;
}
}
return null;
}
/**
* Insert a new node into the skiplist
* @param i the index of the new node
* @param w the node to insert
* @return the node u that precedes v in the
skiplist
*/
protected Node add(int i, Node w) {
Node u = sentinel;
int k = w.height();
int r = h;
int j = -1; // index of u
while (r >= 0) {
while (u.next[r]
!= null && j+u.length[r] < i) {
j += u.length[r];
u = u.next[r];
}
u.length[r]++;
// accounts for new node in list 0
if (r <= k)
{
w.next[r] = u.next[r];
u.next[r] = w;
w.length[r] = u.length[r] - (i - j);
u.length[r] = i - j;
}
r--;
}
return u;
}
/**
* Simulate repeatedly tossing a coin until it comes up
tails.
* Note, this code will never generate a height greater
than 32
* @return the number of coin tosses - 1
*/
protected int pickHeight() {
int z = rand.nextInt();
int k = 0;
int m = 1;
while ((z & m) != 0) {
k++;
m <<=
1;
}
return k;
}
public void add(int i, T x) {
// Hint: bounds checking again!
//if (i < 0 || i > n) throw
new IndexOutOfBoundsException();
if (i > size()-1 || i < 0)
throw new IndexOutOfBoundsException(); //can't have a negative
index
Node w = new Node(x,
pickHeight(), i); //so we can return j at findPred(i)
if (w.height() > h)
h =
w.height();
add(i, w);
}
public T remove(int i) {
// Hint: bounds checking again!
//if (i < 0 || i > n-1) throw
new IndexOutOfBoundsException();
if (i > size()-1 || i < 0)
throw new IndexOutOfBoundsException(); //can't have a negative
index
T x = null;
Node u = sentinel;
int r = h;
int j = -1; // index of node
u
while (r >= 0) {
while (u.next[r]
!= null && j+u.length[r] < i) {
j += u.length[r];
u = u.next[r];
}
u.length[r]--;
// for the node we are removing
if (j +
u.length[r] + 1 == i && u.next[r] != null) {
x = u.next[r].x;
u.length[r] += u.next[r].length[r];
u.next[r] = u.next[r].next[r];
if (u == sentinel && u.next[r] ==
null)
h--;
}
r--;
}
//reset
u = sentinel; r =
0;
return x;
}
public int size() {
return Integer.MAX_VALUE;
}
public String toString() {
// This is just here to help you a bit with debugging
StringBuilder sb = new
StringBuilder();
int i =
-1;
Node u =
sentinel;
while (u.next[0]
!= null) {
i += u.length[0];
u = u.next[0];
sb.append(" " + i + "=>" + u.x);
}
return
sb.toString();
}
public static void main(String[] args) {
Tester.testDefaultList(new
FastDefaultList<Integer>());
}
}
Code Screenshots:
Code for FasterTable.java
package comp2402a3;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
import java.util.Collections;
/**
* This is just a copy of A2Table, your job is to make it
faster
*/
public class FasterTable<T> implements Table<T> {
List<List<T>> tab;
List<Integer> tabValues;
int nrows, ncols;
public FasterTable(Class<T> t) {
nrows = 0;
ncols = 0;
tabValues = new
ArrayList<Integer>(); //keeps track of values in tab
tab = new
ArrayList<List<T>>();
}
public int rows() {
return nrows;
}
public int cols() {
return ncols;
}
public T get(int i, int j) {
if (i < 0 || i > rows() - 1
|| j < 0 || j > cols()-1)
throw new
IndexOutOfBoundsException();
//return
tab.get(i).get(j);
return
tab.get(i).get(tabValues.get(j));
}
public T set(int i, int j, T x) {
if (i < 0 || i > rows() - 1
|| j < 0 || j > cols()-1)
throw new
IndexOutOfBoundsException();
//return tab.get(i).set(j,
x);
return
tab.get(i).set(tabValues.get(j), x);
}
public void addRow(int i) {
if (i < 0 || i > rows())
throw new IndexOutOfBoundsException();
nrows++;
List<T> row = new
ArrayList<T>();
for (int j = 0; j < cols(); j++)
row.add(null);
tab.add(i, row);
}
public void removeRow(int i) {
if (i < 0 || i > rows() - 1)
throw new IndexOutOfBoundsException();
nrows--;
tab.remove(i);
}
public void addCol(int j) {
if (j < 0 || j > cols())
throw new IndexOutOfBoundsException();
ncols++;
for (int i = 0; i < rows() ;i++) {
tab.get(i).add(null);
}
tabValues.add(j,cols()-1);
}
public void removeCol(int j) {
// this method is too slow!
if (j < 0 || j > cols() - 1)
throw new IndexOutOfBoundsException();
ncols--;
for (int i = 0; i < rows(); i++) {
tab.get(i).set(j,null);
}
tabValues.remove(j);
}
public String toString() {
StringBuilder sb = new
StringBuilder();
for (int i = 0; i < rows(); i++)
{
for (int j = 0;
j < cols(); j++) {
sb.append(String.valueOf(get(i, j)));
sb.append(" ");
}
sb.append("\n");
}
return sb.toString();
}
public static void main(String[] args) {
Tester.testTable(new
FasterTable<Integer>(Integer.class));
System.out.println("\nRunning own test...");
Table<Integer> t = new FasterTable<Integer>(Integer.class);
System.out.println("\nAdding 4
rows...");
t.addRow(0);
t.addRow(1); t.addRow(2); t.addRow(3);
System.out.println("\nAdding 4
cols...\n");
t.addCol(0);
t.addCol(1); t.addCol(2); t.addCol(0);
//summary
if (t.rows() == 4 &&
t.cols() == 4) {
System.out.println("Success!");
} else {
System.out.println("Fail.");
}
System.out.println("Num of cols: "
+ t.cols());
System.out.println("Num of rows: "
+ t.rows());
System.out.println("\nRemoving 3
cols...");
t.removeCol(2);
t.removeCol(1); t.removeCol(0);
System.out.println("\nRemoving 2
rows...\n");
t.removeRow(1);
t.removeRow(0);
//summary
if (t.rows() == 2 &&
t.cols() == 1) {
System.out.println("Success!");
} else {
System.out.println("Fail.");
}
System.out.println("Num of cols: "
+ t.cols());
System.out.println("Num of rows: "
+ t.rows());
}
}
Code Screenshots:
Code for Table.java
package comp2402a3;
import java.util.List;
import java.util.ArrayList;
public interface Table<T> {
public int rows();
public int cols();
public T get(int i, int j);
public T set(int i, int j, T x);
public void addRow(int i);
public void removeRow(int i);
public void addCol(int j);
public void removeCol(int j);
public String toString();
}
Code Screenshots:
Code for Tester.java
package comp2402a3;
import java.util.Random;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
public class Tester {
// Handy for testing correctness now that we know A2Table
works
public static <T> boolean tableEquals(Table<T> t1,
Table<T> t2) {
if (t1.rows() != t2.rows()) return false;
if (t1.cols() != t2.cols()) return false;
for (int i = 0; i < t1.rows(); i++) {
for (int j = 0; j < t2.cols(); j++) {
T x1 = t1.get(i, j);
T x2 = t2.get(i, j);
if (x1 != null && x2 == null) return false;
if (x1 == null && x2 != null) return false;
if (x1 != null && !x1.equals(x2)) return false;
}
}
return true;
}
public static boolean testPart1(Table<Integer> t) {
t = new FasterTable<Integer>(Integer.class);
t.addRow(0);
t.addRow(1); t.addRow(2);
t.addRow(3);
t.addCol(0);
t.addCol(1); t.addCol(2); t.addCol(0);
t.removeCol(2);
t.removeCol(1); t.removeCol(0);
t.removeRow(1);
t.removeRow(0);
if (t.cols() == 1 && t.rows() == 2)
return true;
else return false;
}
public static void testTable(Table<Integer> tab) {
long start = System.nanoTime();
boolean result = Tester.testPart1(tab);
long stop = System.nanoTime();
double elapsed = (stop-start)/1e9;
System.out.println("testPart1 returns " + result + " in " + elapsed
+ "s"
+ " when testing a " + tab.getClass().getName());
}
public static boolean testPart2(List<Integer> ell) {
for (int i = 0; i < 10000; i++) {
ell.add(i, i*2);
if (ell.get(i) != i*2) {
return false;
}
}
for (int i = 0; i < 10000; i++) {
if (ell.get(i) != 0 && i%ell.get(i) == 0) {
ell.remove(i);
if (ell.get(i) != null) {
return false;
}
}
}
for (int i = 0; i < 10000; i++) {
ell.set(i, i*3);
if (ell.get(i) != i*3) {
return false;
}
}
for (int i = 0; i < 10000; i++) {
ell.remove(0);
}
for (int i = 0; i < 10000; i++) {
if (ell.get(i) != null) {
return false;
}
}
return true;
}
public static void testDefaultList(List<Integer> ell)
{
long start = System.nanoTime();
boolean result = Tester.testPart2(ell);
long stop = System.nanoTime();
double elapsed = (stop-start)/1e9;
System.out.println("testPart1 returns " + result + " in " + elapsed
+ "s"
+ " when testing a " + ell.getClass().getName());
}
}
Code Screenshots:
Output Screenshots:
Hope it helps, if you like the answer give it thumbs up. Thank you.