I am trying to build a palindrome checker using stacks and a Linked List. I am using generics in order to reuse the nodes and structures to complete two parts of this assignment (to accomplish something different in the next part).
The program is not pushing the letters onto the stack- it is returning nulls. I believe the problem is with the construction of the push method, either in the LinkedStack construction, or the StackDriver implementation, or both. I am just not sure what I am doing wrong; I have tried a multitude of alternatives, and have looked up and tried other methods to construct the push methods but then I get errors and can’t get the program to run at all. (I realize the 2 push methods I have here are different- these are 2 versions I have tried). Should I be looking at some type of boxing for the char c to use the wrapper class?
The program has been set back to the last point at which it ran. The “reversed” popped element seems to be getting the correct amount of characters though- why?
I realize there are other problems with this program as well but I feel like I can’t address them until I get past this stumbling block. Any assistance would be appreciated- thank you!
Mike
The given interface:
public interface Stack<E> {
void push(E data);
E pop();
boolean isEmpty();
int size();
E stackTop();
void clear();
}
The Node and methods:
public class Node<E> {
// create the node structure
private E data;
private Node<E> next;
// getters and setters
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> next) {
this.next = next;
}
}
The Stack:
import java.util.EmptyStackException;
public class LinkedStack<E> implements Stack<E>{
// Create the head and nodeCount variables
private Node<E> head;
private int nodeCount;
// also need to be able to convert letters to capitals.
// constructor for the LinkedStack
public LinkedStack()
{
clear();
}
// A method to push the data onto a stack and increment the node count
public void push(E data) {
head = new Node<E>();
nodeCount++;
}
// pop the head off of the stack and decrement the node count
public E pop() {
E item;
if (head == null)
throw new EmptyStackException();
item = head.getData();
head = head.getNext();
nodeCount--;
return item;
}
// Check if the stack is empty
public boolean isEmpty() {
if (head == null);
return true;
}
// check the size of the node
public int size() {
return nodeCount;
}
// this is the peek method
public E stackTop()
{
if (head == null)
throw new EmptyStackException();
return head.getData();
}
// clear the Linked Stack
public void clear() {
head = null;
nodeCount = 0;
}
// convert to text
public String toString() {
String rtn = "";
if (nodeCount == 0) {
rtn += "<empty>";
}
else {
Node<E> t = head;
while (t != null){
/* return the node data on a line with the head node data
at the beginning of the line and the arrow pointing to
each successive node*/
rtn += t.getData() + "->";
// go on to the next
t = t.getNext();
}
rtn += "null";
}
return rtn;
}
}
And the driver:
import java.util.Iterator;
import java.util.Scanner;
public class StackDriver<E> implements Iterator<E>{
/**
* #param args
*/
public static void main(String[] args) {
//Initialize the driver
StackDriver run = new StackDriver();
run.doIt();
}
public void doIt() {
// gather the input
Scanner keyboard = new Scanner(System.in);
System.out.println("Please enter a phrase. This program will verify" +
" if the phrase is a palindrome.");
// holder for the phrase
String phrase;
// holder for the reversed phrase
String reversed = "";
phrase = keyboard.nextLine().toUpperCase();
System.out.println("You entered: "+ phrase);
// create the two stacks for the characters
LinkedStack<E> alpha = new LinkedStack<E>();
LinkedStack<E> punctuation = new LinkedStack<E>();
//------------------------------------------
for(int i=0; i<phrase.length(); i++)
{
// if the character is a letter, push it onto the letters stack
char c = phrase.charAt(i);
if (true == Character.isLetter(c))
{
// (testing purposes only- remove next line)
System.out.println("LETTER");
String A = Character.toString(c);
// push the letter onto the stack
alpha.push((E) new Node<E>());
}
// else push it onto the characters stack
else
{
// (testing purposes only- remove next line)
System.out.println("NOT LETTER");
String B = Character.toString(c);
// push the character onto the stack
punctuation.push((E) new String(B));
}
// then pop the letters stack
while (!alpha.isEmpty());
{
reversed += alpha.pop();
}
}
//------------------------------------------
// if it equals the String phrase
if (reversed == phrase)
// it is a palindrome
System.out.println("The phrase you entered is a palindrome");
else
System.out.println("The phrase you entered is NOT a palindrome");
System.out.println("phrase: " + phrase);
System.out.println("alpha: " + alpha);
System.out.println("reversed: " + reversed);
}
#Override
public boolean hasNext() {
// TODO Auto-generated method stub
return true;
}
#Override
public E next() {
// TODO Auto-generated method stub
return null;
}
#Override
public void remove() {
// TODO Auto-generated method stub
}
}
And the result:
Please enter a phrase. This program will verify if the phrase is a palindrome.
mom
You entered: MOM
LETTER
LETTER
LETTER
The phrase you entered is NOT a palindrome
phrase: MOM
alpha: <empty>
reversed: nullnullnull
If I got your question properly, I think the issue is indeed your push method in the LinkedStack class. Take a look.
public void push(E data) {
head = new Node<E>();
nodeCount++;
}
You create a new Node, assign it to head and increment the number of nodes of your stack, but you never actually link the older head or populate the new current head, you just replace the head with a new node that has no previous or next element.
// A method to push the data onto a stack and increment the node count
public void push(E data) {
head = new Node<E>();
nodeCount++;
}
This method is wrong. When you push a new node, you need to set it's next to the current head. You also need to populate that node with your data.
This may or may not be your whole problem, but it's definitely part of it...
// A method to push the data onto a stack and increment the node count
public void push(E data) {
head = new Node<E>();
nodeCount++;
}
always replaces head with a new node that contains no data, even though an object of E type was passed. You need to call head.setData(data).
you need to also add to the list rather than replace the head.
if( head == null )
{
head = new Node();
head.setData(data);
}
else {
Node n = new Node();
n.setData(data);
Node last = ...; // leaving getting the last node in the list as an exercise for the reader
last.setNext(n);
}
Related
I am supposed to build a method that will remove the first instance of a given value in a singly-linked list. However, whenever I try to test this method it will get stuck and I have to force the code to terminate.
edit: following advice, I have made a modified version method Contains that now works well and eliminates pointless repetition of Contains. so happily now the code works as it should!
Here is my code for the method:
public boolean remove(Anything m) {
//INCOMPLETE
if (this.first==null) {
System.out.println("there are no values in the list");
return false;
}
boolean returnValue;
returnValue=false;
if (this.contains(m)==true) {
Node temp=first;
while(temp.next!=null) {
if (temp.next.data==m) {
temp=temp.next.next;
temp.next=null;
returnValue=true;
}
else
returnValue=false;
}
}
return returnValue;
}
Here is my code for testing the method:
list13.addFirst("node5"); list13.addFirst("node4"); list13.addFirst("node3"); list13.addFirst("node2"); list13.addFirst("node1");
System.out.println("5-element list: " + list13);
System.out.println("Testing remove...");
System.out.println(list13.remove("node3"));
and just in case, here is the prebuilt code my assignment came with, if needed:
public class CS2LinkedList<Anything>
{
// the Node class is a private inner class used (only) by the LinkedList class
private class Node
{
private Anything data;
private Node next;
public Node(Anything a, Node n)
{
data = a;
next = n;
}
}
private Node first;
private Node last;
public CS2LinkedList()
{
first = null;
}
public boolean isEmpty()
{
return (first == null);
}
public void addFirst(Anything d)
{
Node temp = first;
first = new Node(d,temp);
}
public void clear()
{
first = null;
}
public boolean contains(Anything value)
{
for (Node curr = first; curr != null; curr = curr.next)
{
if (value.equals(curr.data)) {
return true;
}
}
return false;
}
public String toString()
{
StringBuilder result = new StringBuilder(); //String result = "";
for (Node curr = first; curr != null; curr = curr.next)
result.append(curr.data + "->"); //result = result + curr.data + "->";
result.append("[null]");
return result.toString(); //return result + "[null]";
}
```
Some issues:
At a match, you are reassigning to temp the node that follows after the node to be deleted, and then you clear temp.next. That is breaking the list after the node to be deleted.
The while loop does not change the value of temp when the if condition is not true. So the loop can hang.
You can stop the search when you have identified the node to delete. By consequence you don't need the else inside the while loop.
while(temp.next!=null) {
if (temp.next.data==m) {
// skip the node by modifying `temp.next`:
temp.next = temp.next.next;
returnValue=true;
break; // we removed the targeted node, so get out
}
temp = temp.next; // must move to next node in the list
}
It is a pity that you first iterate the list with this.contains(m), only to iterate it again to find the same node again. I would just remove that if line, and execute the loop that follows any way: it will detect whether the list contains the value or not.
Be aware that your function has no provision for removing the first node of the list. It starts comparing after the first node. You may want to cover this boundary case.
Below is the code. The array index represents the small characters(a-z) and index is 26 (number of characters in english alphabets). It is a dictionary of words in which the children[character ascii value-97] points to the next node. The end of word is given bool terminal=true.
All functions are recursive. In delete function, we have to traverse to the end of the word character by character. While traversing, on the second call of recursive delete, I lose all my references and NullPointerException occurs.
The line of code which is making trouble has a comment in front of it. First there is a check if word exist in dictionary or not.
import java.io.File;
import java.util.Scanner;
public class xxx {
public static void main(String[] args) {
Trie trie = new Trie();
if (trie.delete(word)) {
System.out.println("Word deleted");
} else {
System.out.println("Word not present");
}
break;
}
case "S": { //Search for the word
String word = tokens[1];
if (trie.isPresent(word)) {
System.out.println("Word found");
} else {
System.out.println("Word not found");
}
}
This class just calls the recursive functions of the Node class. The trie class gets call from the main class and then shifts the data to recursive functions in Node class
class Trie {
Node root;
public Trie() {
root = new Node();
}
boolean isPresent(String s) { // returns true if s is present, false otherwise
current = root;
for (int i = 0; i < s.length(); i++) {
if (current.children[(int) s.charAt(i) - 97] == null) {
return false;
} else {
current = current.children[(int) s.charAt(i) - 97];
}
}
if (current.terminal == false) {
return false;
}
return true;
}
boolean delete(String s) { // returns false if s is not present, true otherwise
if (!isPresent(s)) {
return false;
}
root.delete(root,s);
return true;
}
int membership() { // returns the number of words in the data structure
return root.membership(root, 0);
}
void listAll() { // list all members of the Trie in alphabetical orber
root.listAll(root, "");
}
}
The children[ascii value-97] will reference a node and this link will represent alphabetic character. The outDegree will make sure that only the given string is deleted. This class has all recursive functions.
class Node {
boolean terminal;
int outDegree;
Node[] children;
public Node() {
terminal = false;
outDegree = 0;
children = new Node[26];
}
public void delete(Node x, String s) {
if (s.length() > 1){
if(i<s.length())
delete(children[s.charAt(0)-97],s.substring(1)); //this is where problem occurs
}
else if(children[((int)s.charAt(0))-97].outDegree>0)
terminal =false;
else if(children[((int)s.charAt(0))-97].outDegree==0){
children[((int)s.charAt(0))-97]=null;
return;
}
if(children[s.charAt(0)-97].outDegree==0)
children[s.charAt(0)-97]=null;
}
}
Your problem is not in the line of code you commented. Your problem is how you initialized the array:
children = new Node[26];
This line of code allocates memory of the array. However, the value of each individual element of the array is set to NULL for object references, unicode NULL character for char primitives, false for boolean primitives, and to 0 for number primitives. If you want this to work, you must initialize the array properly.
My main class is at very bottom, i am trying add nodes in to a list and display them like spcfied in the main class
lList - print linkedlist:
lList.size() - print linkedlist size: 1
lList.size() - print linkedlist size: 1
lList - print linkedlist:
My list wont display, can someone point whats wrong
public interface ListInterface {
//List operations
public boolean isEmpty();
public int size();
public void add(int index, Object item);
public void remove(int index);
public void removeAll();
}// end interface
public class Node {
Object item;
Node next;
Node(Object newItem) {
item = newItem;
next = null;
}
Node(Object newItem, Node nextNode) {
item = newItem;
next = nextNode;
}
public void setItem(Object newItem) {
item = newItem;
} // end setItem
public Object getItem() {
return item;
} // end getItem
public void setNext(Node nextNode) {
next = nextNode;
} // end setNext
public Node getNext() {
return next;
} // end getNext
// end class Node
}
public class ListReferencedBased implements ListInterface {
private Node head;
private int numItems;
public ListReferencedBased(){
numItems = 0;
head = null;
}
#Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return numItems == 0;
}
public int size() {
// TODO Auto-generated method stub
return numItems;
}
private Node find(int index){
Node curr = head;
for(int skip = 0;skip < index;skip++){
curr = curr.next;
}
return curr;
}
public void add(int index, Object item) {
// TODO Auto-generated method stub
if(index == 0 && index < numItems + 1){
if(index ==0){
// insert in begning
Node newNode = new Node(item, head);
head = newNode;
}
else{
Node prev = find(index - 1);
Node newNode = new Node(item,prev.next);
prev.next = newNode;
}
numItems++;
}
}
#Override
public void remove(int index) {
// TODO Auto-generated method stub
if (index == 0){
head = head.next;
}
else{
Node prev = find(index -1);
Node curr = prev.next;
prev.next = curr.next;
}
numItems--;
}
#Override
public void removeAll() {
head = null;
numItems = 0;
}
public String toString() {
Node crunchifyCurrent = head.getNext();
String output = "";
while (crunchifyCurrent != null) {
output += "[" + crunchifyCurrent.toString() + "]";
crunchifyCurrent = crunchifyCurrent.getNext();
}
return output;
}
}
public class Nodemain {
public static void main(String[] args) {
ListReferencedBased lList = new ListReferencedBased();
// add elements to LinkedList
lList.add(0,"1");
lList.add(1,"2");
lList.add(2,"3");
lList.add(3,"4");
lList.add(4,"5");
/*
* Please note that primitive values can not be added into LinkedList
* directly. They must be converted to their corresponding wrapper
* class.
*/
System.out.println("lList - print linkedlist: " + lList);
System.out.println("lList.size() - print linkedlist size: " + lList.size());
// System.out.println("lList.get(3) - get 3rd element: " + lList.get(3));
// System.out.println("lList.remove(2) - remove 2nd element: " + lList.remove(2));
// System.out.println("lList.get(3) - get 3rd element: " + lList.get(3));
System.out.println("lList.size() - print linkedlist size: " + lList.size());
System.out.println("lList - print linkedlist: " + lList);
}
}
First of all, your print is calling toString on Node which will just print the address of Node, not what you want. You need to have a toString method that will return the value in the node in order to display the list properly.
Second, your design may be specified by the teacher, but it's silly to specify adding to a list by position. At the very least, providing addLast and addFirst methods will make it a lot easier to do what you obviously want to do, which is build a list.
In this case, I assume you want addLast because you want to build the list in order.
This is going to be very inefficient because you have to scan through the entire list each time to deposit a new element at the end but presumably that's the assignment.
Start by cleaning up your API if you can. Write addLast that adds the element to the end. Then repost the code if you still have a problem. You really shouldn't be tracking the position to add a value to the end.
I am required to write a method that returns a number - the amount of times an element is found in a linked list. So far I have;
package Question4;
import net.datastructures.Node;
public class SLinkedListExtended<E> extends SLinkedList<E> {
// returns the number of occurrences of the given element in the list
public int count(E elem) {
Node<E> cursor = tail;
int counter = 0;
if ((cursor != null) && (!(cursor.getElement().equals(elem)))) { //tail isnt null and element is not equal to elem
cursor = cursor.getNext(); //go to next node
} else if ((cursor != null) && (cursor.getElement().equals(elem))){ //cursor isn't null and element equals elem
counter++; //increment counter
}
else {
return counter; //return counter
}
return counter;
}
public static void main(String[] args) {
SLinkedListExtended<String> x = new SLinkedListExtended<String>();
x.insertAtTail("abc");
x.insertAtTail("def");
x.insertAtTail("def");
x.insertAtTail("xyz");
System.out.println(x.count("def")); // should print "2"
x.insertAtTail(null);
x.insertAtTail("def");
x.insertAtTail(null);
System.out.println(x.count("def")); // should print "3"
System.out.println(x.count(null)); // should print "2"
}
}
I have extended to a class which compiles correctly, so I know the problem is in my method. I can't figure out what to do, my code returns 0, which is probably the counter integer remaining at 0 and not going through the loop statement. Any ideas are appreciated.
Edit. SLinkedList code:
import net.datastructures.Node;
public class SLinkedList<E> {
protected Node<E> head; // head node of the list
protected Node<E> tail; // tail node of the list (if needed)
protected long size; // number of nodes in the list (if needed)
// default constructor that creates an empty list
public SLinkedList() {
head = null;
tail = null;
size = 0;
}
// update and search methods
public void insertAtHead(E element) {
head = new Node<E>(element, head);
size++;
if (size == 1) {
tail = head;
}
}
public void insertAtTail(E element) {
Node<E> newNode = new Node<E>(element, null);
if (head != null) {
tail.setNext(newNode);
} else {
head = newNode;
}
tail = newNode;
size++;
}
public static void main(String[] args) { // test
SLinkedList<String> list = new SLinkedList<String>();
list.insertAtHead("lol");
}
}
Maybe you should use a while loop instead of an if clause
**while** ((cursor != null) && (!(cursor.getElement().equals(elem)))) {
The code in count is not in a loop, so it'll just return after the first element.
Try this:
public int count(E elem) {
Node<E> cursor = tail;
int counter = 0;
while (true)
{
if ((cursor != null) && (!(cursor.getElement().equals(elem)))) { //tail isnt null and element is not equal to elem
cursor = cursor.getNext(); //go to next node
} else if ((cursor != null) && (cursor.getElement().equals(elem))){ //cursor isn't null and element equals elem
counter++; //increment counter
}
else {
return counter; //return counter
}
}
}
Also, note that cursor.getElement().equals(elem) will return a NullPointerException when cursor.getElement() is null. The easiest way to deal with this is probably to write a separate equals method:
boolean equals(E e1, E e2)
{
if (e1 == null)
return e2 == null;
if (e2 == null)
return false;
return e1.equals(e2);
}
Also, presumably Node<E> cursor = tail; makes it point to the end of the list and presumably you want Node<E> cursor = head; instead.
One of the fundamental things that you were missing was a loop. Since you are essentially searching for something, you want to loop through the entire list. Once you run into an element that matches the one that you are searching for, you want to increment the count by 1. Once you have finished looping through the entire list, you want to return that count. So this is my solution. I keep it simple so you could understand:
import java.util.LinkedList;
public class Duplicates<E> extends LinkedList<E> {
public static void main(String[] args) {
Duplicates<String> duplicates = new Duplicates<String>();
duplicates.add("abc");
duplicates.add("def");
duplicates.add("def");
duplicates.add("xyz");
System.out.println(duplicates.duplicateCount("def"));
duplicates.add(null);
duplicates.add("def");
duplicates.add(null);
System.out.println(duplicates.duplicateCount("def"));
System.out.println(duplicates.duplicateCount(null));
}
public int duplicateCount(E element) {
int count = 0;
for (E e : this) {
if (e == element) {
count++;
}
}
return count;
}
}
Output:
2
3
2
I suggest you combine Martin's answer (which tells you how to count the elements) with this, which tell you how to be able to use foreach - you just have to make your SLinkedListExtended implement Iterable, whioch should be something liek the follwoing (you could do this on SLinkedList, but I'm assuming you were told not to alter the code for that one):
public class SLinkedListExtended<E> extends SLinkedList<E> implements Iterable<E> () {
public Iterator<E> iterator() {
final Node<E> itHead = head;
return new Iterator<E>() {
Node<E> current = itHead;
long position = 0;
public boolean hasNext() {
return current != null && position < size;
}
public E next() {
current = current.getNext();
++position;
return current.getElement();
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
};
}
};
I can't vouch for all the details, but this should cover most of it. You may also consider using equals instead of ==, but don't forget to check the elements for nullity.
next should only be called if hasNext is true, so it's not a problem if it throws an exception (but it should be a NoSuchElementException to keep in line with the contract).
Implementing Iterable makes your class compatible with the Collections library, hence the support for foreach, but you can use it to do raw iteration by calling iterator, hasNext and next yourself.
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).