How can I implement a Dynamic Array Stack in Java? - java

I need to modify a class to create a dynamic array stack.
My code at this point looks something like this:
public class DynamicArrayStack<E> implements Stack<E> {
private E[] elems; //used to store the elements
public static final int defaultIncrement = 25;
private final int increment;
private int top;
#SuppressWarnings( "unchecked" )
public DynamicArrayStack( int increment ) {
this.increment = increment;
elems = (E[]) new Object[ increment ];
top = 0;
}
/**
* Constructor with no parameter that will initialize
* the stack to have an array whose size is the value
* of increment and memorise that value as the value
* of increment.
*/
public void ArraySize() { }
public boolean isEmpty() {
return top == 0;
}
public E peek() {
return elems[ top-1 ];
}
public E pop() {
// save the top element
E saved = elems[ --top ];
// scrub the memory, then decrements top
elems[ top ] = null;
return saved;
}
public void push( E elem ) {
// stores the element at position top, then increments top
elems[ top++ ] = elem;
}
public String toString() {
StringBuffer b;
b = new StringBuffer( "DynamicArrayStack: {" );
for ( int i=top-1; i>=0; i-- ) {
if ( i!=top-1 ) {
b.append( "," );
}
b.append( elems[ i ] );
}
b.append( "}" );
return b.toString();
}
}
How do I edit the first constructor to set increment as the initial size of the stack and that same value to be used when increasing or decreasing the size of the array. My method for doing this seems way too simple. Parameter must be > 0 and a fixed number of cells are added or removed when the size of the array changes.
The second constructor should set the stack to have an array whose size is the value of increment. I keep getting errors here because I can't figure out how to do that because I thought that was already set in the first constructor. Also the size of the array as the value of increment.
Also how do I make this class capable of changing the capacity of the stack and into which method should I place that code?

Here is the simple java code to implement it:
1)Stack based:
public class DynamicArrayStack {
public static void main(String[] args) {
DynamicStack dstack=new DynamicStack(2);
System.out.println("--Pushing--");
dstack.push(1);
dstack.push(2);
dstack.display();
dstack.push(3);
dstack.push(2);
dstack.push(5);
dstack.display();
System.out.println("--Popping--");
dstack.pop();
dstack.pop();
dstack.pop();
dstack.display();
}
}
class DynamicStack {
private int top;
private int capacity;
private int[] array;
public DynamicStack(int cap) {
capacity = cap;
array = new int[capacity];
top = -1;
}
public void push(int data) {
if (isFull()){
expandArray(); //if array is full then increase its capacity
}
array[++top] = data; //insert the data
}
public void expandArray() {
int curr_size = top + 1;
int[] new_array = new int[curr_size * 2];
for(int i=0;i<curr_size;i++){
new_array[i] = array[i];
}
array = new_array; //refer to the new array
capacity = new_array.length;
}
public boolean isFull() {
if (capacity == top+1)
return true;
else
return false;
}
public int pop() {
if (isEmpty()) {
System.out.println("Stack is empty");
return -1;
} else {
reduceSize(); //function to check if size can be reduced
return array[top--];
}
}
public void reduceSize() {
int curr_length = top+1;
if (curr_length < capacity / 2) {
int[] new_array = new int[capacity / 2];
System.arraycopy(array, 0, new_array, 0, new_array.length);
array = new_array;
capacity = new_array.length;
}
}
public boolean isEmpty() {
if (top == -1)
return true;
else
return false;
}
public void display() {
for (int i = 0; i <= top; i++) {
System.out.print(array[i] + "=>");
}
System.out.println();
System.out.println("ARRAY SIZE:" + array.length);
}
}
OUTPUT:
--Pushing--
1=>2=>
ARRAY SIZE:2
1=>2=>3=>2=>5=>
ARRAY SIZE:8
--Popping--
1=>2=>
ARRAY SIZE:4
2)Link List based:
public class LinkListStack {
public static void main(String[] args) {
StackList stack = new StackList();
System.out.println("--Pushing--");
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
stack.push(6);
stack.display();
System.out.println("--Popping--");
stack.pop();
stack.pop();
stack.display();
}
}
class Node {
private int data;
private Node next;
public Node(int d) {
data = d;
next = null;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
class StackList {
private Node top;
private int length;
public StackList() {
length = 0;
top = null;
}
public void push(int data) {
Node temp = new Node(data);
if (top == null) {
top = temp;
} else {
temp.setNext(top);
top = temp;
}
length++;
}
public int pop() {
Node temp=top;
int data = top.getData();
top = top.getNext();
temp=null;
length--;
return data;
}
public void display() {
Node temp = top;
if (isEmpty()) {
System.out.println("Stack is empty");
} else {
while (temp != null) {
System.out.print(temp.getData() + "=>");
temp = temp.getNext();
}
}
System.out.println();
}
public boolean isEmpty() {
return (top == null);
}
}
OUTPUT:
--Pushing--
6=>5=>4=>3=>2=>1=>
--Popping--
4=>3=>2=>1=>

Default constructor
Your default constructor could simply call your other constructor with a default increment value. For example:
public DynamicArrayStack() {
this(defaultIncrement);
}
Expanding the array
The correct place to expand the array is within the push method. When attempting to add a new element you can check if the array is large enough, and if not create a new larger array. For example you could do the following:
#Override
public E push(final E elem) {
// Check if we need to expand the array
if (elems.length - 1 == top) {
#SuppressWarnings("unchecked")
final E[] newElems = (E[]) new Object[elems.length + increment];
System.arraycopy(elems, 0, newElems, 0, elems.length);
elems = newElems;
}
// stores the element at position top, then increments top
elems[top++] = elem;
return elem;
}
If you want to shrink the array the sensible place to do this would be in the pop() method. You might want to consider only reducing the length when (top + (increment*2))<elems.length to avoid repeatedly copying arrays when you're on the boundary.

Related

How to speed up Depth First Search method?

I'm trying to do a Depth First Search of my graph, and something is slowing it down quite a lot and I'm not sure what.
Here is my Bag code:
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Bag<Item> implements Iterable<Item> {
private Node<Item> first; // beginning of bag
private Node<Item> end;
private int n; // number of elements in bag
public int label;
public int edges;
public static class Node<Item> {
private Item item;
private Node<Item> next;
public int label;
public int edges;
}
public Bag() {
first = null; // empty bag initialized
end = null;
n = 0;
}
public void add(Item item) {
if (n==0) {
Node<Item> head = new Node<Item>(); // if bag is empty
first = head;
end = head;
head.item = item; // new node both first and end of bag
edges++;
n++;
}
else {
Node<Item> oldlast = end; // old last assigned to end of node
Node<Item> last = new Node<Item>();
last.item = item;
oldlast.next = last; // new node added after old last
end = last;
n++; // size increased
edges++;
}
}
public Iterator<Item> iterator() {
return new LinkedIterator(first); // returns an iterator that iterates over the items in this bag in arbitrary order
}
public class LinkedIterator implements Iterator<Item> {
private Node<Item> current;
public LinkedIterator(Node<Item> first) {
current = first; // iterator starts at head of bag
}
public boolean hasNext() { return current != null; }
public void remove() { throw new UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new NoSuchElementException(); // if there is next item, current is moved to next
Item item = current.item;
current = current.next;
return item; // item is returned
}
}
}
Here is my driver:
import java.util.ArrayList;
import java.util.Random;
public class Driver {
public static ArrayList<Integer> randomNum(int howMany) {
ArrayList<Integer> numbers = new ArrayList<Integer>(howMany);
Random randomGenerator = new Random();
while (numbers.size() < howMany) {
int rand_int = randomGenerator.nextInt(10000);
if (!numbers.contains(rand_int)) {
numbers.add(rand_int);
}
}
return numbers;
}
public static void main(String[] args) {
ArrayList<Integer> num = randomNum(100);
Graph G = new Graph(num);
System.out.println("The length of longest path for this sequence with graph is: " + G.dfsStart(num));
}
}
I send an ArrayList of random integers to my dfsStart method from the driver, which looks at all the different paths for each starting node in my graph. my DepthFirstSearch method calls the getAdjList for each starting node to find its neighbors using my Bag adj, and then works its way down each path before backtracking.
Here is my Graph code, containing my longest path method:
import java.util.ArrayList;
import java.util.NoSuchElementException;
public class Graph {
public final int V; // initializing variables and data structures
public Bag<Integer>[] adj;
public int longestPath;
public Graph(ArrayList<Integer> numbers) {
try {
longestPath = 0;
this.V = numbers.size();
adj = (Bag<Integer>[]) new Bag[V]; // bag initialized
for (int v = 0; v < V; v++) {
adj[v] = new Bag<Integer>();
}
for (int i = 0; i < V; i++) {
adj[i].label = numbers.get(i);
int j = (i + 1);
while (j < numbers.size()) {
if (numbers.get(i) < numbers.get(j)) {
addEdge(i, numbers.get(j));
}
j++;
}
}
}
catch (NoSuchElementException e) {
throw new IllegalArgumentException("invalid input format in Graph constructor", e);
}
}
public void addEdge(int index, int num) {
adj[index].add(num);
}
public int getIndex(int num) {
for (int i = 0; i < adj.length; i++) {
if (adj[i].label == num) {
return i;
}
}
return -1;
}
public Bag<Integer> getAdjList(int source) {
Bag<Integer> adjList = null;
for (Bag<Integer> list : adj) {
if (list.label == source) {
adjList = list;
break;
}
}
return adjList;
}
public int dfsStart(ArrayList<Integer> numbers) {
for (int i=0;i<numbers.size();i++) {
// Print all paths from current node
depthFirstSearch(numbers.get(i),new ArrayList<>(300));
}
return longestPath;
}
public void depthFirstSearch(int src, ArrayList<Integer> current) {
current.add(src);
Bag<Integer> srcAdj = getAdjList(src);
if (srcAdj.size() == 0) {
// Leaf node
// Print this path
longestPath = Math.max(longestPath, current.size());
}
for (int links : srcAdj) {
depthFirstSearch(links, current);
}
current.remove(current.size()-1);
}
}
I believe the suggestion below helped get rid of the error, but it is still unbelievably slow when trying to find the longest path in a graph of more than 150 vertices.
Even for a small dense graph there can be many unique paths from a src node. I tested for this input [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25] there are 16777216 unique paths from all nodes. So you can expect OOM for bigger inputs. one way is to update the longestPath as soon as a path is found instead of adding it to the list.
Change this to later.
addtoCount(current.size());
to
longestPath = Math.max(longestPath, current.size());
Make sure longestPath is global and initialized to 0 before every test case.
Well, I do not know JAVA but that is an incredible lot of code for doing a simple thing such as depth first search.
In C++ it is done like this:
void cPathFinder::depthFirst(
int v)
{
// initialize visited flag for each node in graph
myPath.clear();
myPath.resize(nodeCount(), 0);
// start recursive search from starting node
depthRecurse(v, visitor);
}
void cPathFinder::depthRecurse(
int v )
{
// remember this node has been visited
myPath[v] = 1;
// look for new adjacent nodes
for (int w : adjacent(v))
if (!myPath[w])
{
// search from new node
depthRecurse(w);
}
}

How can I hold the max of a stack?

Been banging my head against a wall for a week and cannot seem to get anywhere. I want to be able to get the max from the stack and keep it in the stack so in the end there is a only one value in the Stack and that is the max. I believe my algorithm to keep the max is correct, but I think my pop method is malfunctioning and I cannot figure out why. Any guidance is appreciated. Both files I am working with are included
import java.io.File;
import java.io.IOException;
import java.util.ListIterator;
import java.util.Random;
public class LinkedListStack {
DoublyLinkedList<Integer> list = new DoublyLinkedList<Integer>();
public int size() {
if (list.isEmpty()) {
System.out.println("Stack is empty");
}
return list.size();
}
public void push(Integer s) {
list.add(s);
}
public Integer pop() {
/* need help with this method */
}
public Integer top() {
return list.iterator().next();
}
public boolean isEmpty() {
return list.isEmpty();
}
public String displayStack() {
return (list.toString());
}
public static void main(String[] args) throws IOException {
LinkedListStack stack = new LinkedListStack();
int n, seed;
File outputFile;
File dir = new File(".");
if (args.length > 0) {
n = Integer.parseInt(args[0]);
seed = Integer.parseInt(args[1]);
}else {
n = 10;
seed = 1;
}
if (args.length == 3) {
outputFile = new File(args[2]);
} else {
outputFile = new File(dir.getCanonicalPath() + File.separator + "Files/testOut_Stack");
}
OutputWriter out = new OutputWriter(outputFile);
Random r = new Random(seed);
Integer nextval;
for (int i = 0; i < n; i++) {
nextval = r.nextInt(10000);
if (stack.isEmpty()) {
stack.push(nextval);
}
if (nextval > stack.top()) {
stack.pop();
stack.push(nextval);
}
/* retain the max value that you see among the integers generated in the stack.
* In the end there should be only one integer in stack, which is the max value
*/
}
// write the content of stack -- which is the max value -- to file
out.writeOutput(stack.displayStack());
}
}
import java.io.File;
import java.io.IOException;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Random;
import csci3230.hw3.OutputWriter;
public class DoublyLinkedList<Item> implements Iterable<Item> {
private int n; // number of elements on list
private Node pre; // sentinel before first item
private Node post; // sentinel after last item
public DoublyLinkedList() {
pre = new Node();
post = new Node();
pre.next = post;
post.prev = pre;
}
// linked list node helper data type
private class Node {
private Item item;
private Node next;
private Node prev;
}
public boolean isEmpty() {
return (n == 0);
// your code
}
public int size() {
return n;
// your code
}
// add the item to the list
public void add(Item item) {
Node last = post.prev;
Node x = new Node();
x.item = item;
x.next = post;
x.prev = last;
post.prev = x;
last.next = x;
n++;
// your code
}
public ListIterator<Item> iterator() { return new DoublyLinkedListIterator(); }
// assumes no calls to DoublyLinkedList.add() during iteration
private class DoublyLinkedListIterator implements ListIterator<Item> {
private Node current = pre.next; // the node that is returned by next()
private Node lastAccessed = null; // the last node to be returned by prev() or next()
// reset to null upon intervening remove() or add()
private int index = 0;
public boolean hasNext() {
return (index < n); // your code
}
public boolean hasPrevious() {
return (index > 0);
// your code
}
public int previousIndex() {
return (index - 1);
// your code
}
public int nextIndex() {
return (index + 1);
// your code
}
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
lastAccessed = current;
Item item = current.item;
current = current.next;
index++;
return item;
// your code
}
public Item previous() {
if (!hasPrevious()) throw new NoSuchElementException();
current = current.prev;
index--;
lastAccessed = current;
return current.item;
// your code
}
// replace the item of the element that was last accessed by next() or previous()
// condition: no calls to remove() or add() after last call to next() or previous()
public void set(Item item) {
if (lastAccessed == null) throw new IllegalStateException();
lastAccessed.item = item;
// your code
}
// remove the element that was last accessed by next() or previous()
// condition: no calls to remove() or add() after last call to next() or previous()
public void remove() {
if (lastAccessed == null) throw new IllegalStateException();
Node x = lastAccessed.prev;
Node y = lastAccessed.next;
x.next = y;
y .prev = x;
n--;
if (current == lastAccessed) {
current = y;
}
else {
index--;
}
lastAccessed = null;
// your code
}
// add element to list
public void add(Item item) {
Node x = current.prev;
Node y = new Node();
Node z = current;
y.item = item;
x.next = y;
y.next = z;
z.prev = y;
y.prev = x;
n++;
index++;
lastAccessed = null;
// your code
}
}
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
}
}
You can keep the first integer you pop as a temporary "largestValue" and compare every subsequent integer you pop with it to see whether you should replace it. At the very of your function, pop all values and add the largestValue back onto it.

CircularArrayQueue implementation Java

I am trying to implement a CircularArrayQueue. I've been given a JUnit test which my queue must pass.I suppose I am doing something wrong with the front and rear pointers. How should i approach learning data structures and algorithms ?
import java.util.NoSuchElementException;
public class CircularArrayQueue implements MyQueue {
private Integer[] array;
// initial size of the array
private int N;
private int front;
private int rear;
public CircularArrayQueue() {
this.N = 10;
array = new Integer[N];
front = rear = 0;
}
public CircularArrayQueue(int size) {
this.N = size;
array = new Integer[N];
front = rear = 0;
}
// enqueues an element at the rear of the queue
// if the queue is already full it is resized, doubling its size
#Override
public void enqueue(int in) {
if (rear == N) {
if (front == 0) {
resize();
array[rear] = in;
rear++;
} else {
array[rear] = in;
rear = 0;
}
} else {
array[rear] = in;
rear++;
}
}
public void resize() {
Integer[] temp = new Integer[array.length * 2];
for (int i = 0; i < array.length; i++) {
temp[i] = array[i];
}
temp = array;
}
// dequeues an element
// if the queue is empty a NoSuchElement Exception is thrown
#Override
public int dequeue() throws NoSuchElementException {
if (isEmpty()) {
throw new NoSuchElementException("The queue is full");
}
int headElement = array[front];
if (front == N) {
array[front] = null;
front = 0;
} else {
array[front] = null;
front++;
}
return headElement;
}
#Override
public int noItems() {
return N - getCapacityLeft();
}
#Override
public boolean isEmpty() {
return (getCapacityLeft() == N);
}
// return the number of indexes that are empty
public int getCapacityLeft() {
return (N - rear + front) % N;
}
}
Your initialization is absolutely fine, and we do start with:
front = rear = 0;
Befor adding an item to the Q, we modify rear as
rear = (rear + 1) % N;
The % allows us to maintain the circular property of the queue. Also you must be wondering that if we modify rear before adding any item, then 0 index is left empty, well we have to compromise here with one array item being left blank, in order to have correct implementations for checking of isEmpty() and isFull() functions:
That said, the correct code for isEmpty() is:
#Override
public boolean isEmpty()
{
return front == rear;
}
You should also have a function isFull() like:
#Override
public boolean isFull()
{
return front == ((rear + 1) % N);
}
Also the line temp = array; in your resize() should be array = temp; and you must also update the value of N after calling resize().
Hence, the correct code is:
import java.util.NoSuchElementException;
public class CircularArrayQueue implements MyQueue
{
private Integer[] array;
//initial size of the array
private int N;
private int front;
private int rear;
private int count = 0;//total number of items currently in queue.
public CircularArrayQueue()
{
this.N = 10;
array = new Integer[N];
front = rear = 0;
}
public CircularArrayQueue(int size)
{
this.N = size;
array = new Integer[N];
front = rear = 0;
}
//enqueues an element at the rear of the queue
// if the queue is already full it is resized, doubling its size
#Override
public void enqueue(int in)
{
count++;
if (isFull())
{
resize();
rear = (rear + 1) % N;
array[rear] = in;
}
else
{
rear = (rear + 1) % N;
array[rear] = in;
}
}
public void resize()
{
Integer[] temp = new Integer[array.length*2];
N = array.length*2;
for(int i=0; i<array.length; i++)
{
temp[i] = array[i];
}
array = temp;
}
//dequeues an element
// if the queue is empty a NoSuchElement Exception is thrown
#Override
public int dequeue() throws NoSuchElementException
{
if(isEmpty())
{
throw new Exception("The queue is empty");
}
front = (front + 1) % N;
int headElement = array[front];
count--;
return headElement;
}
#Override
public int noItems()
{
return count;
}
#Override
public boolean isEmpty()
{
return front == rear;
}
#Override
public boolean isFull()
{
return front == ((rear + 1) % N);
}
//return the number of indexes that are empty
public int getCapacityLeft()
{
return N - 1 - count;
}
}

using Java Loop for ArrayList to print each time

I have a method which I basically want to simulate first filling the queue and then after that removing the first person and adding a new person each time in my public void mySimulation() method:
import java.util.*;
public class People {
private final int DEFAULT_CAPACITY = 100;
private int front, rear, count;
private ArrayList<thePeople> people;
private int theMaxCapacity;
//-----------------------------------------------------------------
// Creates an empty queue using the specified capacity.
//-----------------------------------------------------------------
public People(int initialCapacity) {
front = rear = count = 0;
people = new ArrayList<thePeople>(Collections.nCopies(5, (thePeople) null));
}
//-----------------------------------------------------------------
// Adds the specified element to the rear of the queue, expanding
// the capacity of the queue array if necessary.
//-----------------------------------------------------------------
public void enque(thePeople element) {
if (this.isFull()) {
System.out.println("Queue Full");
System.exit(1);
} else {
people.set(rear, element);
rear = rear + 1;
if (rear == people.size()) {
rear = 0;
}
count++;
}
}
//-----------------------------------------------------------------
// Removes the element at the front of the queue and returns a
// reference to it. Throws an EmptyCollectionException if the
// queue is empty.
//-----------------------------------------------------------------
public thePeople dequeue() {
if (isEmpty()) {
System.out.println("Empty Queue");
}
thePeople result = people.get(front);
people.set(front, null);
front = (front + 1) % people.size();
count--;
return result;
}
//-----------------------------------------------------------------
// Returns true if this queue is empty and false otherwise.
//-----------------------------------------------------------------
public boolean isEmpty() {
return (count == 0);
}
//-----------------------------------------------------------------
// Returns the number of elements currently in this queue.
//-----------------------------------------------------------------
public int size() {
return count;
}
public boolean isFull() {
return count == people.size();
}
public void mySimulation() {
Random rand1 = new Random();
thePeople theM = null;
if (this.isFull()) {
this.people.remove(0);
System.out.println("Enqueueing...");
this.enque(people.get(rand1.nextInt(people.size())));
thePeople r1 = people.get(rear - 1);
System.out.println(people.toString());
System.out.println(r1);
for (int e = 0; e < people.size(); e++) {
if (people.get(e) instanceof thePeople) {
System.out.println("G");
} else {
System.out.println("D");
}
}
}
}
//-----------------------------------------------------------------
// Returns a string representation of this queue.
//-----------------------------------------------------------------
#Override
public String toString() {
String result = "";
int scan = 0;
while (scan < count) {
if (people.get(scan) != null) {
result += people.get(scan).toString() + "\n";
}
scan++;
}
return result;
}
public static void main(String[] args) {
People Q1 = new People(25);
thePeople call1 = new thePeople("John King", "001 456 789");
thePeople call2 = new thePeople("Michael Fish", "789 654 321");
Q1.enque(call1);
Q1.enque(call2);
System.out.println(Q1.toString());
ArrayList<thePeople> callerDetails = new ArrayList<>(Arrays.asList(call1, call2));
Random rand = new Random();
for (int z = 0; z <= 4; z++) {
Q1.enque(callerDetails.get(rand.nextInt(callerDetails.size())));
}
System.out.println(Q1.toString());
}
}
any suggestions on how I could repeat this process such that I will first check that the queue is full,
if so remove the first item and add a new person to it using my arrayList each time i my my public void mySimulation() method: as I cant get my head round this at the moment?
Your code is filled with errors:
First make sure you remove the "the" you accidently placed before people in many lines of your code .
Then adjust some of your methods to the right parameters and return types.
As for you question:
it is simple
public void MySimulation(){
if(Queue.isFull()){
Queue.dequeue;}
Queue.enqueue;}

Searching and deleting values in a circular linked list

I am trying to make an application that will loop through a circular linked list. As it does so, it will use another linked list of index values, and it will use these values to delete from the circular linked list.
I have it set up now where it should fetch the index value to be deleted from my random linked list via runRandomList() method. It then uses the rotate() method to loop through the circular linked list and deletes the value from it. It will then add the deleted value to "deletedLinked list". Then, control should return back to runRandomList() method and it should feed the rotate() method the next value from the random linked list. The circular linked list should begin traversing where it left off. It should keep track of the count and node it is on. The count should reset to 0 when it reaches the first node, so it can properly keep track of which index it is on.
Unfortunately, this is not happening. I have been trying different things for the last few days as the code stands right now; it enters into a continuous loop. the issue appears to be in the rotate method.
This is the rotate method code. My thought was the counter would advance until it matches the index input. If it reaches the first node, the counter would reset to 0 and then start to increment again until it reaches the index value.
private void rotate(int x)
{
while(counter <= x)
{
if(p == names.first)
{
counter = 0;
}
p = p.next;
counter++;
}
deleteList.add((String) p.value);
names.remove(x);
}
This is my linked list class:
public class List<T>{
/*
helper class, creates nodes
*/
public class Node {
T value;
Node next;
/*
Inner class constructors
*/
public Node(T value, Node next)
{
this.value = value;
this.next = next;
}
private Node(T value)
{
this.value = value;
}
}
/*
Outer class constructor
*/
Node first;
Node last;
public int size()
{
return size(first);
}
private int size(Node list)
{
if(list == null)
return 0;
else if(list == last)
return 1;
else
{
int size = size(list.next) + 1;
return size;
}
}
public void add(T value)
{
first = add(value, first);
}
private Node add(T value, Node list)
{
if(list == null)
{
last = new Node(value);
return last;
}
else
list.next = add(value, list.next);
return list;
}
public void setCircularList()
{
last.next = first;
}
public void show()
{
Node e = first;
while (e != null)
{
System.out.println(e.value);
e = e.next;
}
}
#Override
public String toString()
{
StringBuilder strBuilder = new StringBuilder();
// Use p to walk down the linked list
Node p = first;
while (p != null)
{
strBuilder.append(p.value + "\n");
p = p.next;
}
return strBuilder.toString();
}
public boolean isEmpty()
{
boolean result = isEmpty(first);
return result;
}
private boolean isEmpty(Node first)
{
return first == null;
}
public class RemovalResult
{
Node node; // The node removed from the list
Node list; // The list remaining after the removal
RemovalResult(Node remNode, Node remList)
{
node = remNode;
list = remList;
}
}
/**
The remove method removes the element at an index.
#param index The index of the element to remove.
#return The element removed.
#exception IndexOutOfBoundsException When index is
out of bounds.
*/
public T remove(int index)
{
// Pass the job on to the recursive version
RemovalResult remRes = remove(index, first);
T element = remRes.node.value; // Element to return
first = remRes.list; // Remaining list
return element;
}
/**
The private remove method recursively removes
the node at the given index from a list.
#param index The position of the node to remove.
#param list The list from which to remove a node.
#return The result of removing the node from the list.
#exception IndexOutOfBoundsException When index is
out of bounds.
*/
private RemovalResult remove(int index, Node list)
{
if (index < 0 || index >= size())
{
String message = String.valueOf(index);
throw new IndexOutOfBoundsException(message);
}
if (index == 0)
{
// Remove the first node on list
RemovalResult remRes;
remRes = new RemovalResult(list, list.next);
list.next = null;
return remRes;
}
// Recursively remove the element at index-1 in the tail
RemovalResult remRes;
remRes = remove(index-1, list.next);
// Replace the tail with the results and return
// after modifying the list part of RemovalResult
list.next = remRes.list;
remRes.list = list;
return remRes;
}
}
This contains the main(), runRandomList(), and rotate() methods.
public class lottery {
private int suitors;
private List<String> names;
private List<Integer> random;
private List<String> deleteList = new List<>();
private int counter;
private Node p;
public lottery(int suitors, List<String> names, List<Integer> random)
{
this.suitors = suitors;
this.names = names;
this.random = random;
p = names.first;
}
public void start()
{
//Set names list to circular
names.setCircularList();
runRandomList(random);
}
public void runRandomList(List<Integer> random)
{
Node i = random.first;
while(i != null)
{
rotate((int) i.value, counter, p);
i = i.next;
}
}
public List getDeleteList()
{
return deleteList;
}
private void rotate(int x, int count, Node p)
{
Node i = p;
while(count <= x)
{
if(i == names.first)
{
count = 0;
}
i = i.next;
count++;
}
deleteList.add((String) i.value);
names.remove(x);
p = i;
counter = count;
}
public static void main(String[] args)
{
List<String> namesList = new List<>();
namesList.add("a");
namesList.add("b");
namesList.add("c");
namesList.add("d");
namesList.add("e");
namesList.add("f");
List<Integer> randomList = new List<>();
randomList.add(3);
randomList.add(1);
randomList.add(5);
randomList.add(4);
randomList.add(0);
lottery obj = new lottery(6, namesList, randomList);
obj.start();
System.out.println(obj.getDeleteList());
}
}
As I suspected it was the rotate method, this is the solution.
private void rotate(int x, int count)
{
while(count != x)
{
p = p.next;
count++;
if(count == x)
{
deleteList.add((String)p.value);
counter = x;
}
if(count >= suitors)
{
for (int j = 0; j < x ; j++)
{
p = p.next;
}
deleteList.add((String)p.value);
counter = x;
count = x;
}
}
}

Categories

Resources