Converting a Single Linked List to a Double Linked List - java

I have here a single linked list for a program that makes a collage. This runs perfectly but I was wondering how to make it a double linked list. I really have no idea what a double linked is though or how to create one. Any help would be appreciated...
There are 3 classes.
class LinearCollage
{
private Picture myArray[];
private class Node
{
Picture data;
Node pNext;
};
private Node pFirst;
private Node pLast;
private int nPictures;
private Picture clipboard;
public LinearCollage()
{
pFirst = null;
pLast = null;
nPictures = 0;
}
public void addPictureAtEnd(Picture aPictureReference)
{
Node temp = new Node();
temp.data = aPictureReference;
temp.pNext = null;
if( pLast == null )
{
pLast = temp;
pFirst = temp;
}
else
{
pLast.pNext = temp;
pLast = temp;
}
nPictures++;
}
public Picture makeCollage()
{
int collageHeight = 400;
int collageWidth = 400;
for( Node finger = pFirst; finger != null; finger = finger.pNext )
{
System.out.println("Process Picture " + finger.data);
}
Picture retval = new Picture(collageHeight,collageWidth);
int i = 0;
for( Node finger = pFirst; finger != null; finger = finger.pNext )
{
System.out.println("Process Picture " + finger.data);
finger.data.compose(retval, 50*i, 50*i);
i++;
}
return retval;
}
public void cutMiddle()
{
int cutIndex = nPictures-1;
clipboard = myArray[cutIndex];
for( int i = cutIndex; i < nPictures - 1; i++ )
{
myArray[i] = myArray[i + 1];
}
nPictures--;
}
public void cutEnd()
{
int cutIndex = nPictures;
clipboard = myArray[cutIndex];
for( int i = cutIndex; i<nPictures - 1; i++)
{
myArray[i] = myArray[i + 1];
}
nPictures--;
}
public void pasteEnd()
{
myArray[nPictures] = clipboard;
nPictures++;
}
public boolean isFull()
{
return false;
}
public boolean isEmpty()
{
return nPictures == 0;
}
}
import java.util.Scanner;
class LineCollageMaker
{
public static void main(String a[])
{
LinearCollage myCollage;
Scanner uiInput = new Scanner(System.in);
myCollage = new LinearCollage();
FileChooser.pickMediaPath();
boolean inputting = true;
while( inputting )
{
System.out.println("Another picture? Type Y if so.");
String answer = uiInput.next();
if(answer.equals("Y"))
{
Picture pin = new Picture(FileChooser.pickAFile());
myCollage.addPictureAtEnd(pin);
}
else
{
inputting = false;
}
}
Picture firstToShow = myCollage.makeCollage();
firstToShow.show();
//YOU Code the user inteface loop and dispatch to methods
//of myCollage here..
boolean done = false;
while( !done )
{
System.out.println("MENU (CASE SENSITIVE!)");
System.out.println("CM - cut middle and move it to the clipboard");
System.out.println("PE - paste clipboard to end");
System.out.println("CE - cut end and move it to clipboard");
System.out.println("XX - stop running this program");
String command = uiInput.next();
if(command.equals("XX"))
done = true;
else if(command.equals("CM"))
{
if(myCollage.isEmpty())
{
System.out.println("Can't cut from an empty collage.");
}
else
{
myCollage.cutMiddle();
myCollage.makeCollage().show();
}
}
else if(command.equals("PE"))
{
if(myCollage.isFull())
{
System.out.println("Can't paste to an empty collage.");
}
else
{
myCollage.pasteEnd();
myCollage.makeCollage().show();
}
}
else if(command.equals("CE"))
{
if(myCollage.isEmpty())
{
System.out.println("Can't copy from an empty collage.");
}
else
{
myCollage.cutEnd();
myCollage.makeCollage().show();
}
}
else
System.out.println("Unrecognized command. Try again.");
}
}
}
public class Node
{
//le class variables
private Picture myPic;
private Node next;
//le constructors
public Node(Picture heldPic)
{
myPic=heldPic;
next=null;
}
public void setNext(Node nextOne)
{
this.next=nextOne;
}
public Node getNext()
{
return this.next;
}
public Picture getPicture()
{
return this.myPic;
}
//le methods
public void drawFromMeOn(Picture bg)
{
Node current;
int currentX=0, currentY=bg.getHeight()-1;
current = this;
while (current != null)
{
current.drawMeOn(bg,currentX, currentY);
currentX = currentX + current.getPicture().getWidth();
current=current.getNext();
}
}
private void drawMeOn(Picture bg, int left, int bottom)
{
this.getPicture().blueScreen(bg, left, bottom-this.getPicture().getHeight());
}
}

A doubly linked list is simply a linked list where every element has both next and prev mebers, pointing at the elements before and after it, not just the one after it in a single linked list.
so to convert your list to a doubly linked list, just change your node to be:
private class Node
{
Picture data;
Node pNext;
Node pPrev;
};
and when iterating the list, on each new node add a reference to the previous node.

A doubly-linked list takes a singly-linked list one step further by also having a reference to the previous node, rather than just the next one.
I confess I am slightly confused by your code as it looks like you have a private class for Node and then another public class for it. To make this a doubly-linked list add another Node instance variable into your Node class which references the previous node, and then update this variable when you add in new nodes.

You can convert Single linked list to Double linked list via a concept called XOR based linked list. The beauty of XOR truth table makes suitable for this use case.
Check this out : https://www.geeksforgeeks.org/xor-linked-list-a-memory-efficient-doubly-linked-list-set-1/

Related

How to create a linked list in java without importing linked lists

i am a CS student in college and i am having trouble with this project where i am supoosed to create a linked list using nodes without importing linked lists, as well as doing a some methods with the list. i am a beginner when it comes to coding, so assume i know nothing, because that is probably the case lol.
import java.io.*;
import java.lang.*;
public class List {
public int listCount = 0;
public char[] linkedList;
public List() throws FileNotFoundException {
}
public List(char[] array) throws FileNotFoundException {
if (array.length == 1) {
Node head = new Node(array[0]);
} else if (array.length > 1) {
Node head = new Node(array[0]);
Node traverse = head;
for (int i = 1; i < array.length; i++) {
while (traverse.nextNode != null) {
traverse = traverse.nextNode;
}
traverse.nextNode = new Node(array[i]);
listCount++;
}
}
}
public List(String w) throws FileNotFoundException {
char[] array2 = new char[w.length()];
for (int i = 0; i < w.length(); i++) {
array2[i] = w.charAt(i);
}
List str = new List(array2);
}
/* Find the character at a index
#param int index
return the character at the chosen index
*/
public char charAt(int index) throws IndexOutOfBoundsException {
char results = linkedList[0];
if (index < linkedList.length && index >= 0) {
results = linkedList[index];
}
return results;
}
public String concat(int index1, int index2) {
return null;
}
/* Determine if the list is empty
return whether the given conditions are true or false
*/
public boolean isEmpty() {
for (int i = 0; i < linkedList.length; i++) {
if (!linkedList.equals(null)) {
System.out.println("This list is not empty");
return false;
}
}
System.out.println("List is empty");
return true;
}
/* Determine the size of the list
return the size of the list
*/
public int size() {
return listCount;
}
/* Create a new String between 2 index's including the start and end index
#param beginIndex is the starting point of the new String
#endIndex is the ending point of new String
return the new String
*/
public String subString(int beginIndex, int endIndex) {
return null;
}
public void insert(Object x) throws IndexOutOfBoundsException {
if (listCount > 100 || listCount < 0) {
throw new IndexOutOfBoundsException("Bag is too large");
} else {
this.linkedList[listCount] = (char) x;
listCount++;
}
}
}
i appreciate any help or pointers ahead of time. we are using a separate node, helper, and driver class as well as a .txt file to assign into my list. i am stuck on the concat and substring methods too, but i want to make sure i am getting the framework correct first. thank you again.
If i understand your question correctly, you are asking how to access a specific type without importing it.
Imports are required to identify which type is referenced when it is used by its simple name. To reference a type without declaring it in the imports you need to use its fully qualified name. For instance
java.util.List<String> someList = new java.util.ArrayList<>();
works without importing List and ArrayList because by declaring the package the class is in it is clear which class is being referenced.
I'll try to do the code later, but here is a book that i found that may help you.
https://cin.ufpe.br/~grm/downloads/Data_Structures_and_Algorithms_in_Java.pdf
I bought a book about DATA STRUCTURE from Pearson company, and it's really a good book, but i don't remember much, it's something like this, that i did in a hurry:
public class List {
private Node head = null;
private Node foot = null;
private Node newNode = null;
private Node auxNode = null;
public List() {
this.head = new Node();
this.foot = new Node();
}
public class Node {
private int adress;
private Node nextNode;
}
public void add(int value) {
this.newNode = new Node();
newNode.adress = value;
if (head == null) {
// Head of the list receive the values of the NEW NODE, so the head of the list
// is not null enymore
head = newNode;
head.nextNode = null;
} else {
// In this case Head is not null
/*The auxiliary node will receive the head and the new Node will become the new Head from the list*/
auxNode = new Node();
auxNode = head;
/*
while(auxNode.nextNode != null ) {
}
auxNode = head;
//head of the list is empty, so we can add the new node
head = newNode;//Here the new node is empty because was transfered to the head
head.nextNode = auxNode; //The head of the list receive the old node that used to be the head
if (head.nextNode == null) {
head.nextNode = newNode;
} else if (head.nextNode != null) {
}*/
}
}
}
```
I hope this help you to get some lead

LinkedList isn't taking input

I seem to be having some problems with inserting values into a linked list. I am trying to create a program for the Josephus problem and I am suppose to take 3 numbers from the user. The first number is how many "people" there are, say its 4 you would have a list of 1,2,3,4. This is where I am stuck. Every time I enter in the 3 ints my program returns saying the List is empty and I can't figure out why. If anyone could help explain it would be greatly appreciated, thanks!
Main
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
long[] numbers = new long[3];
LinkedList circle = new LinkedList();
System.out.println("Please enter 3 numbers");
for (int i = 0; i < 3; i++)
{
numbers[i] = input.nextLong();
}
for (int i = 0; i < numbers[0]; i++)
{
circle.insertLink();
circle.move();
}
circle.getCurrent();
}
Link
class Link
{
public long dData;
public Link next;
public Link(long dd)
{
dData = dd;
}
public Link(int d, Link n)
{
this(d);
next = n;
}
public void displayLink()
{
System.out.print(dData + " ");
}
}
Linked List
class LinkedList
{
private Link current;
private int id;
public LinkedList()
{
current = null;
id = 1;
}
public void move()
{
current = current.next;
}
public boolean isEmpty()
{
if(current == null)
System.out.println("The List is empty");
return current == null;
}
public Link getCurrent()
{
return current;
}
public void setCurrent(int id)
{
while(current.dData != id)
move();
}
public Link getNext()
{
return current.next;
}
public void insertLink()
{
if(!isEmpty())
{
Link newlink = new Link(id++, current.next);
current.next = newlink;
}
else
{
Link newlink = new Link(id++);
newlink.next = newlink;
current = newlink;
}
}
public Link deleteLink()
{
Link temp = current.next;
if(current != current.next)
current.next = current.next.next;
else
current = null;
return temp;
}
}
when first time you call insertLink() methos you always will get The List is empty print. because at initialization the current variable of your linked list class is null. just remove System.out.println("The List is empty"); from your code.
public boolean isEmpty()
{
return current == null;
}
override toString() method to see your list
You are taking three inputs from user and iterating with first element of numbers array, i think it should be
for (int i = 0; i < numbers.length; i++)
{
circle.insertLink();
circle.move();
}
And at the first time when you insert the link, isEmpty() method checks your current variable is null or not if it is then it print the "The list is empty". so just remove that line.
System.out.println("The List is empty");

Output( ) from a Set class with Singly Linked List Hash Table

I have code that I have been working on going on 10 hours now, and for the life of me, I am unable to get the output( ) of my Set.java to work. Unfortunately I am not allowed to just import the Iterator or HashTable classes from java library. Any ideas or advice would really help.
public class SLL {
public class Node {
private int data;
private Node next;
public Node() {
data = 0;
next = null;
}
public Node(int newData, Node linkValue) {
data = newData;
next = linkValue;
}
public int getData() {
return data;
}
public Node getLink() {
return next;
}
} // End of Node inner class
private Node head;
public SLL() {
head = null;
}
public void addToStart(int itemData) {
head = new Node(itemData, head);
}
public boolean contains(int item) {
return (find(item) != null);
}
/**
* Finds the first node containing the target item, and returns a reference
* to that node. If target is not in the list, null is returned.
*/
public Node find(int target) {
Node position = head;
int itemAtPosition;
while (position != null) {
itemAtPosition = position.data;
if (itemAtPosition == target) {
return position;
}
position = position.next;
}
return null; // target was not found
}
public void outputList() {
Node position = head;
while (position != null) {
System.out.print(position.data + " ");
position = position.next;
}
System.out.println();
}
}
This is the class that I have been working on:
public class Set {
private SLL[] hashArray; // DO NOT MODIFY THIS LINE
private int size = 10; // DO NOT MODIFY THIS LINE
// DO NOT MODIFY THIS METHOD
public Set() {
hashArray = new SLL[size];
}
// DO NOT MODIFY THIS METHOD
private int computeHash(int s) {
return s % size;
}
// COMPLETE BELOW
public void add(int x)
{
int hash = computeHash(x); // Get hash value
SLL list = hashArray[hash];
if(hashArray[hash] == null)
hashArray[hash] = new SLL();
else if(!list.contains(x));
{
// Only add the target if it's not already
// on the list.
hashArray[hash].addToStart(x);
}
}
public void output()
{
SLL tmp = new SLL();
SLL.Node temp = tmp.head;
for(int i = 0; i < size; i++)
{
if(temp == null)
//I think a new instance needs to be created
while(temp.getLink() != null)
{
System.out.println(i + temp.getData() + toString() + " ");
}
}
}
}
And this is the tester it should work with:
public class Tester{
// Have this method to display your name, instead.
static void displayName(){
System.out.println("Program written by Tony.\n");
}
// DO NOT MODIFY THE MAIN METHOD
public static void main(String[] args){
displayName();
Set set1 = new Set();
Set set2 = new Set();
set1.add(3);
set1.add(3);
set1.add(13);
set1.add(23);
set1.add(4);
set1.add(5);
set2.add(15);
set2.add(6);
set2.add(6);
System.out.println("Contents of set 'set1': ");
set1.output();
System.out.println("Contents of set 'set2': ");
set2.output();
System.out.println();
}
}
You need to iterate through the entries in your hash array, and for each non-null entry, iterate through the linked list:
public void output() {
for (int i = 0; i < hashArray.length; i++) {
if (hahArray[i] != null) {
hashArray[i].outputList();
}
}
}
In your for loop as below:
if(temp == null)
//I think a new instance needs to be created
while(temp.getLink() != null)
{
System.out.println(i + temp.getData() + toString() + " ");
}
You should be checking temp != null and you are not moving your node from one to other to traverse over each elements. So you should change it to:
while(temp != null) {
System.out.println(temp.getData() + " ");
temp = temp.getLink();
}
So changing the output( ) a bit to
public void output()
{
SLL tmp = new SLL();
SLL.Node temp = tmp.head;
for (SLL s : hashArray) {
System.out.println(toString() + " " + s);}
}
It still only prints "Programmed by Tony"
and "Contents of set 1:" "Contents of set 2: " without the actual set data?

How to code Queue in Java

I'm trying to make a Queue in java.
The problem is that I don't know how to remove(?) a value from the array, the index value which I dequeue.
This is my code.
front() method is the dequeue part. and I used iter_ to set the current index position.
but as you can see, it dequeue's the corret value though the value still remains inside the array:(
public class IntQueue {
private int[] items_;
private int top_;
private int capacity_;
private int iter_;
public IntQueue(int capacity)
{
if(capacity <=0) capacity = 10;
capacity_ = capacity;
top_=0;
count_ = 0;
iter_=0;
items_= new int[capacity_];
}
public void push_back(int value)
{
if(top_>= capacity_)
overflow();
items_[top_++]=value;
count_++;
}
public int front()
{
if(top_<=0)
return 0;
int temp=0;
temp=items_[iter_];
count_--;
iter_++;
return temp;
}
public IntQueue clone()
{
IntQueue result = new IntQueue(capacity_);
for(int i=0 ; i<top_; ++i)
{
result.push_back(items_[i]);
}
/*for(int i=0 ; i<top_ ; ++i)
{
result.items_[i] = items_[i];
}*/
return result;
}
public void log()
{
for(int i=0 ; i <top_; ++i)
{
System.out.print(items_[i]);
if(i<top_ -1)
System.out.print(", ");
}
System.out.println();
}
}
private void overflow()
{
int[] newItem = new int[capacity_*2];
for(int i=0 ; i <top_; ++i)
newItem[i] = items_[i];
items_=newItem;
capacity_ *=2;
}
public static void main(String args[])
{
IntQueue queue = new IntQueue(2);
System.out.println("queue push 3: "); queue.push_back(3);
System.out.println("queue push 2: "); queue.push_back(2);
System.out.println("queue push 1: "); queue.push_back(1);
System.out.print("queue log: "); queue.log();
System.out.println("front " + queue.front());
System.out.println("front " + queue.front());
System.out.print("queue log: "); queue.log();
System.out.println("queue push 12: "); queue.push_back(12);
System.out.println("queue push 11: "); queue.push_back(11);
System.out.println("queue push 21: "); queue.push_back(21);
System.out.println("queue push 31: "); queue.push_back(31);
System.out.print("queue log: "); queue.log();
System.out.println("front " + queue.front());
System.out.println("front " + queue.front());
System.out.print("clone queue log: "); queue.clone().log();
}
}
What I don't get about your implementation is the following:
in the front method you're using iter_, but nowhere else. What is it good for?
if you're not using some kind of variable to keep track of what was removed without actually removing it, technically you'd need to shift all the items of the array to the left by one position, such that the first item is gone. This however is an O(N) operation.
It's easier to implement a queue using a linked list instead of an array.
When building a queue using an array, you can make a cyclic "pointer" to the head of the array, that you can use to retrieve the top.
Popping from the array is simply done by increasing this cyclic pointer.
Maintain an int variable: top, and once you need to pop an element do top = (top + 1) % items_.length
Retrieving the head is simple using items_[top].
Make sure you are guarding against popping elements that are not there (popping from an empty array).
You will probably also need to maintan a size variable for the queue's size.
Below I share my proposed solution for a simple thread-safe FIFO queue :D
public class Queue extends Object {
private int numElements;
private Node first;
private Node last;
/**
* Helper linked list class
*/
private static class Node {
private Object item;
private Node next;
}
/**
* Creates a new Queue object.
*/
public Queue() {
numElements = 0;
first = last = null;
}
/**
* Puts an object at the end of the queue.
*
* #param object
*/
public void putObject(Object object) {
synchronized (this) {
Node newNode = new Node();
newNode.item = object;
newNode.next = null;
if ( numElements == 0 ) {
first = last = newNode;
} else {
last.next = newNode;
last = newNode;
}
numElements += 1;
}
}
/**
* Gets an object from the beginning of the queue. The object is removed
* from the queue. If there are no objects in the queue, returns null.
*/
public Object getObject() {
synchronized (this) {
Object item = null;
if ( numElements > 0 ) {
item = first.item;
first = first.next;
numElements -= 1;
if (numElements == 0) {
last = null;
}
}
return item;
}
}
}
You cant remove an element from an array like a List. You need to move the values up and set the last index of the array as null. Take a look at the source of a java class that implement Queue.remove() method. For example following is the code from removeAt(int index) method of ArrayBlockingQueue.
void removeAt(int i) {
final E[] items = this.items;
// if removing front item, just advance
if (i == takeIndex) {
items[takeIndex] = null;
takeIndex = inc(takeIndex);
} else {
// slide over all others up through putIndex.
for (;;) {
int nexti = inc(i);
if (nexti != putIndex) {
items[i] = items[nexti];
i = nexti;
} else {
items[i] = null;
putIndex = i;
break;
}
}
}
--count;
notFull.signal();
}
when you design a queue, you need to decide the priority like how you are going to add and remove element from it.You can go through this link and implement it similar to this.
FIFO
A typical example is :
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
Queue<String> qe=new LinkedList<String>();
qe.add("b");
qe.add("a");
qe.add("c");
qe.add("e");
qe.add("d");
Iterator it=qe.iterator();
System.out.println("Initial Size of Queue :"+qe.size());
while(it.hasNext())
{
String iteratorValue=(String)it.next();
System.out.println("Queue Next Value :"+iteratorValue);
}
// get value and does not remove element from queue
System.out.println("Queue peek :"+qe.peek());
// get first value and remove that object from queue
System.out.println("Queue poll :"+qe.poll());
System.out.println("Final Size of Queue :"+qe.size());
}
}
First of all, you can't delete an item from an array, you can just overwrite it. You can use a List instead.
Another option is to use a circular queue, as amit's answer pointed out.
A simple solution using array is:
int queue[SIZE];
int first = 0;
int last = 0;
void enque(int i) {
if(last == SIZE)
throw new RuntimeExeption("Queue is full");
queue[last++] = i;
}
int deque() {
if(first == last)
throw new RuntimeExeption("Queue is empty");
return queue[first++];
}
Check this: it has enqueue and dequeue methods:
import java.io.*;
import java.lang.*;
class clrqueue
{
DataInputStream get=new DataInputStream(System.in);
int a[];
int i,front=0,rear=0,n,item,count=0;
void getdata()
{
try
{
System.out.println("Enter the limit");
n=Integer.parseInt(get.readLine());
a=new int[n];
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
void enqueue()
{
try
{
if(count<n)
{
System.out.println("Enter the element to be added:");
item=Integer.parseInt(get.readLine());
a[rear]=item;
rear++;
count++;
}
else
System.out.println("QUEUE IS FULL");
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
void dequeue()
{
if(count!=0)
{
System.out.println("The item deleted is:"+a[front]);
front++;
count--;
}
else
System.out.println("QUEUE IS EMPTY");
if(rear==n)
rear=0;
}
void display()
{
int m=0;
if(count==0)
System.out.println("QUEUE IS EMPTY");
else
{
for(i=front;m<count;i++,m++)
System.out.println(" "+a[i]);
}
}
}
class Myqueue
{
public static void main(String arg[])
{
DataInputStream get=new DataInputStream(System.in);
int ch;
clrqueue obj=new clrqueue();
obj.getdata();
try
{
do
{
System.out.println(" 1.Enqueue 2.Dequeue 3.Display 4.Exit");
System.out.println("Enter the choice");
ch=Integer.parseInt(get.readLine());
switch (ch)
{
case 1:
obj.enqueue();
break;
case 2:
obj.dequeue();
break;
case 3:
obj.display();
break;
}
}
while(ch!=4);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
This is the code i implemented and is working fine in my system.
import java.util.Arrays;
public class Queue {
public int[] queue = new int[3];
int head = -1, tail =-1;
public void enqueue(int N){
if(tail == (queue.length-1))
queue = Arrays.copyOf(queue,2*queue.length);
if(head == -1){
head++;
tail++;
queue[head] = N;
}
else {
tail++;
queue[tail] = N;
}
}
public int dequeue(){
if(head == -1)
throw new IllegalStateException("Cannot dequeue if queue is empty");
int firstItem = queue[head];
if (head == tail) {
head = -1;
tail = -1;
}
else
head++;
return firstItem;
}
public void display(){
for (int i = head; i<= tail ; i++){
System.out.println("Display: " + queue[i]);
}
}
}
public class Main {
public static void main(String[] args) {
Queue queue = new Queue();
queue.enqueue(10);
queue.enqueue(20);
queue.enqueue(30);
queue.enqueue(40);
queue.display();
int dequeue = queue.dequeue();
System.out.println(dequeue);
queue.display();
int dequeue1 = queue.dequeue();
System.out.println(dequeue1);
queue.display();
}
}

Traversing a custom linked list

I'm writing a program to simulate memory fragmentation. The input file tells what segments need to be input at what time.
A sample file is:
N
C 200
P 1 2 3
P 2 3 4
P 2 3 1
R
E
where C is the memory size, P is the segment in the order (size, start time, and life time), and R (should) print out a report showing what segments, and any holes are in memory and where.
One of the rules of this assignment is to create a linked list of the events, where insertions and deletions of the segments are created as events, and I need to traverse the event list.
UPDATE: I have something different, but I know for sure it's not inserting my Events into the Event List. I don't understand why. Does anyone see where my logic is off?
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class TestEventList{
public static void main(String[] args){
//read file
File file = new File("b.txt");
try {
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
//send it to interpret file method:
interpretFile(line);
}
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} //end try-catch
}
public static void interpretFile(String command) {
EventList evtList = new EventList();
Scanner sc = new Scanner(command);
char initialCommand = command.charAt(0);
if (initialCommand == 'N') {
System.out.println("Name");
} else {
}//end else
//file error
char commandCode = command.charAt(0);
String skip = sc.next(); //skips next character to get to integers
switch (commandCode) {
case 'C':/*create Memory! which means, create Event!
Form: Event(int startTime, Segment memSegment)*/
int size = sc.nextInt();
Segment defaultMemoryNode = new Segment(size, 100, false );
/*create event node*/
Event insertDefaultNode = new Event(0, defaultMemoryNode);
/*insert this event*/
evtList.insertEvent(insertDefaultNode);
break;
case 'P':
int segmentSize = sc.nextInt();
int segmentStart = sc.nextInt();
int segmentLife = sc.nextInt();
int segmentExpiration = segmentLife + segmentStart;
Segment memorySegment = new Segment(segmentSize, segmentExpiration, true );
Event addSegment = new Event(segmentStart, memorySegment);
evtList.insertEvent(addSegment);
memorySegment.occupied = false;
Event removeSegment = new Event(segmentExpiration, memorySegment);
evtList.insertEvent(removeSegment);
break;
case 'R':
evtList.traverseEventList();
break;
case 'E':
System.exit(0);
}//end switch
}//end interpretfile method
} //end class T.E.L.
/*This class has-a Linked List, has-a memoryNode, has-a Segment*/
class MemoryList{
private Node memoryNode = new Node();
private Segment memorySegment = new Segment();
private LinkedList memoryList = new LinkedList();
Node head;
Node current;
public MemoryList(){
super();
}
/*define blocks and holes*/
public void insertBlock(Segment memorySegment) {
current = head;
if (current == null) {
memoryList.Add(memorySegment);
System.out.println(memorySegment.size);
}
else {
System.out.println("Checking for room");
System.out.println(current.getSize());
int invalidFit=0;
if(current.getStatus() == false && current.getSize()>=memorySegment.size){
System.out.println("Verified space");
int freeSpace = current.getSize() - memorySegment.size;
memoryList.Add(memorySegment);
createHole(freeSpace);
current = current.next;
} //end if
else {
current = current.next;
} //end else
}//end else
} //end insert block
public void removeBlock(Segment expiredSegment){
current = head;
//search for segment
while(current.next != null){
if(current.getTimetoLeave() == expiredSegment.timeToLeave
&& current.getSize() == expiredSegment.size){
memoryList.Remove(expiredSegment);
int freespace = expiredSegment.size;
createHole(freespace);
}
else{
current = current.next;
}
}//end while
}
private void createHole(int space) {
Node hole = new Node(space, 100, false);
memoryList.Add(hole);
//test if there are two holes together. if so, mergeHoles.
}
*Merge 2 Consecutive Holes*/
private void mergeHoles(Node a, Node b) {
//getPrev(a); //find previous of node a
//use the size through the end of a's prev to
//get start of prev.next (a)+
//make a point to b.next?
} //end mergeHoles
public void traverseMemoryList(){
current = head;
if(current == null){
System.out.println("Memoryless");
}
else{
while(current.next != null){
if(memoryNode.getStatus() == false){
System.out.println("Hole");
current = current.next;
}
}
System.out.println("Segment of size " + current.getSize());
current = current.next;
}
}
} //end MemoryList
class MemoryNode extends Node{
public MemoryNode(){
super();
}
}
class Segment{
int size;
int timeToLeave;
boolean occupied;
/*constructor*/
public Segment(){
}
public Segment(int newSize, int newTime, boolean isOccupied){
this.size = newSize;
this.timeToLeave = newTime;
this.occupied = isOccupied;
}
}
class Node {
private int size;
private int timeToDepart;
boolean occupied; // True if segment, false if hole
Node next;
public Object data; //data in a node
public Node() {
}
public Node(int segmentSize, int timeToLeave, boolean type) {
this.size = segmentSize;
this.timeToDepart = timeToLeave;
this.occupied = type;
}
public int getSize() {
return size;
}
public void setSize(int segmentSize) {
size = segmentSize;
}
public int getTimetoLeave() {
return timeToDepart;
}
public void setTimetoLeave(int timeToLeave) {
timeToDepart = timeToLeave;
}
public void setStatus(boolean type) {
occupied = type;
}
public boolean getStatus() {
return occupied;
}
} //end Node
/* class LL has-a Node*/
class LinkedList{
private Node listNode= new Node();
Node current;
Node head;
Node prev;
int size;
/*Constructors:*/
public LinkedList() {
super();
}
public LinkedList(int j, int k, boolean l) {
super(); //essentially the same as a node
}
/*LL proprietary methods*/
/*test if the list is empty, to avoid NullPointerException*/
public boolean isEmpty() {
return head == null;
}
//insert method:
public void Add(Object data1) {
listNode.data = data1;
/*special case: list is empty*/
if (isEmpty()) {
listNode.next = head;
head = listNode;
head.data = listNode.data;
}
else{
current = head;
while(current.next != null)
{
current.data = data1;
current.next = null;
head = current;
}
current.data = data1;
current.next = head; //newNode now points to head
head = current; //now newNode is the head
}
}
public void Remove(Object delData) {
/*pointers*/
//special case: if head is the removed node;
if (current.data == delData) {
head = current.next;
} else {
prev = head; //it's not the head, keep moving.
current = current.next;
while (current.next != null) { //reached end of list
if (current.data == delData) { //if
prev.next = current.next; //just skip the current node
} else {
prev = current; //now prev is that node
current = current.next; //current is the next node
}
} //end while
//what if current.next = null (it's at the end)?
if (current.next == null && current.data == delData) {
prev.next = null;
}
}//end else
}
public void traverse(){
if(head== null){
System.out.println("no elements to show");
}
else{
current = head;
while(current.next != null){
current = current.next;
}
}}
}// end LL class
/*class EventList has-an Event, is-a LinkedList*/
class EventList{
private Event event = new Event();
private LinkedList evtList = new LinkedList();
private MemoryList memList = new MemoryList();
Node current;
Node head;
int time; //set to the most recent time
/*constructor*/
public EventList(){
super();
}
public void actionOfEvent(Event event1){
Segment p = event.getMemorySegment();
if(p.occupied == true){
insertSegment(event1);
}
else
removeSegment(event1);
}
//a linked list to control creation of events
public void insertEvent(Event event) {
current = head;
if(current == null){
evtList.Add(event);
System.out.println("Added 1st event " + event.startTime);
}
else{
while(current.next != null){
if(event.startTime <= event.getTime()){
//if the event start was before the current time...
evtList.Add(event);
current = current.next;
}
else{
current = current.next;
}
}//end while
evtList.Add(event);
System.out.println("Added 2nd event");
}
}//end insertEvent
public void traverseEventList(){
current = head;
if(current == null){
System.out.println("At time " + event.getTime());
System.out.println("uneventful");
}
else{
while (current.next != null){
Segment segment1 = event.getMemorySegment();
if(segment1.occupied = true){
memList.insertBlock(segment1);
System.out.println(segment1.size + " inserted");
}
else{
memList.removeBlock(segment1);
System.out.println(segment1.size + " removed from memory.");
}
}
}
}
public void insertSegment(Event addEvent){
addEvent.getMemorySegment();
memList.insertBlock(addEvent.getMemorySegment());
}
public void removeSegment(Event expEvent){
}
} //end eventList
/*class Event is-a Node*/
class Event{
int startTime;
Segment memoryNode;
int time;
public Event(){
super();
}
//pretty much the same as Node.
public Event(int newStartTime, Segment newMemNode){
super();
this.startTime = newStartTime;
this.memoryNode = newMemNode;
}
public void setTime(int newStartTime){
time = newStartTime;
}
public int getTime(){
return time;
}
public void setMemorySegment(Segment newMemNode){
memoryNode = newMemNode;
}
public Segment getMemorySegment(){
return memoryNode;
}
}//end class Event
class Report{
int currentTime= 0;
//this creates and prints the segments/holes in the list at curTime
}
I ran your code and it seems that you never call:
setMemoryNode();
This is causing NullPointerExceptions.
Also:
Some of the multiple event instances are being caused by these lines:
EventSequenceList expiredNode = new EventSequenceList(newMemNode,
1, expir, 1, true);
insertEvent(expiredNode);
I will edit this as I see more.
Just a few (other) remarks
Design
You use a lot of inheritance. Is that really necessary? Later on, for production code, you should consider using composition instead of inheritance and code against interfaces. That will remove a lot of ugly dependencies and improve maintainability. Now you have
EventSequenceList is-a MemoryList is-a LinkedList is-a Node
Just from the names, I have some doubt, that a LinkedList really is-a Node. I expect a Node in trees or graphs and even there it's usually a has-a relationship.
Naming
Sometimes you break with Java naming conventions: method names should not start with a capital letter (like Add). Sometimes you use one-letter-variable names (like in most of your constructors).
Sometimes a methodname does not tell us, what the method is really doing (like iterpretFile which actually does not interpret a file but only a single command that may have been read from a file)
The more I look at the assignment, the more I get the feeling, that you'll get stuck with your design sooner or later (more sooner than later). From what I read, what is required:
One event model class. A Class, that represents an insertion or deletion event.
One memory model class. A Class, that represents the entire memory
One segment model class. A Class that represents a segment. A memory class has a list or an array of segments
One linked list that holds all events. This custom linked list may be capable of inserting an event at the right place
One reporting class. A class that can create and print a report.
One input file parser. It will use the input to
create a memory class (with an appropriate number of segments)
create insertion and deletion events from the P lines
insert the events in the linked list
Absolutely no inheritance is needed.
Edit - in response to your last comments
A memory has-an array of cells. The cells are indexed, starting with 0. They are not linked, so I actually don't see any reason to use a LinkedList here. A memory model could look like:
public class Memory {
private int[] cells;
public Memory(int size) { cells = new int[size]; }
public void store(int index, int value) {
if (index < 0 || index >= size) throw new IllegalArgumentException("..");
cells[index] = value;
}
public int read(int index) {
if (index < 0 || index >= size) throw new IllegalArgumentException("..");
return cells[index];
}
}
A segment could be seen as a subclass of Memory. In real life, a segment is requested from a memory manager and the manager allocates a region, if possible. Segments are totally independant, no link between them, no use for a LinkedList here. A quick draft:
public class MemoryManager {
private Memory managedMemory;
public MemoryManager(Memory memory) { this.memory = memory; }
public Segment getSegment(int size) {
int startAddress = allocateSegment(int size);
if (startAddress != -1) {
return new Segment(this, startAddress, size);
}
return null;
}
}
public class Segment extends Memory {
private MemoryManager memoryManager;
private int startAddress; // usually - a handle, so that the memoryManager can
// relocate the segment - we keep it simple
public Segment(MemoryManager memoryManager, int startAdress, int size) {
super(size);
this.memoryManager = memoryManager;
this.startAddress = startAddress;
}
Now back to the events.
One of the rules of this assignment is to create a linked list of the events [eventList = new EventList<Event>()] , where insertions and deletions of the segments are created as events [new Event(EventType.INSERT, int time, Segment segment)); new Event(EventType.DELETE, int time, Segment segment);] , and I need to traverse the event list [for(Event event:eventList)].
That's the task. implement an Event class, implement an EventList class, implement a small enum EventType. The challenge is to implement an insert method in EventClass that inserts two events for one P line at the right places (timestamps).

Categories