Traversing a custom linked list - java

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).

Related

LinkedList with if statements?

So i got this one task to do, about LinkedList, you can take a look on my Main file, also got to mention that my "//The conditions" part is wrong and I just put something as an idea, but that's actually not really working
import java.util.*;
public class Main {
public static void main(String[] args){
ArrayList nokiaAL = new ArrayList();
LinkedList phoneAL = new LinkedList();
//input
Smartphone a = new Smartphone("Nokia","Nokia 7 Plus",1300,260101);
Smartphone b = new Smartphone("Samsung","Galaxy S8",900,220100);
Smartphone c = new Smartphone("Xiaomi","Mi 10",1500,150031);
Smartphone d = new Smartphone("Nokia","3310",250,101001);
Smartphone e = new Smartphone("Samsung","Galaxy Y",400,774101);
Smartphone f = new Smartphone("Apple","iPhone 7",1100,316300);
phoneAL.insertAtFront(f);
phoneAL.insertAtFront(e);
phoneAL.insertAtFront(d);
phoneAL.insertAtFront(c);
phoneAL.insertAtFront(b);
phoneAL.insertAtFront(a);
//process
Object r = (Object) phoneAL.getFirst();
while (r != null) {
System.out.print(" "+r);
r = (Object) phoneAL.getNext();
}
//The conditions
//If nokia + the price $1200+, it will save all the info about nokia
//If brand samsung + model Galaxy Y, It will count the total of the phone
Object obj;
int countSamsung = 0;
for(int i=0;i<phoneAL.size();i++){
obj = phoneAL.get(i);
Smartphone obj2 = (Smartphone) obj;
if(obj2.getBrand().equalsIgnoreCase("Nokia")){
nokiaAL.add(obj2);
}
if(obj2.getBrand().equalsIgnoreCase("Samsung")){
if(obj2.getModel().equalsIgnoreCase("Galaxy Y")){
countSamsung++;
}
}
}
//output
System.out.println("\n");
System.out.println("Details about Nokia phone more than RM1200:"+nokiaAL.toString());
System.out.println("Quantity of Samsung model Galaxy Y: " + countSamsung);
}
}
I know how to print all the details in the LinkedList, the main point here is, you can't add or change anything of other .java files, you can only edit the Main.java file, is it even possible? here's my Smartphone and LinkedList code.
public class Smartphone {
String brand;//e.g: Nokia, Samsung
String model;//e.g: Lumia, Galaxy Y, Note S
double price;
int warranty;//warranty (in year)
Smartphone() {
}
public Smartphone(String a, String b, double c, int d){
this.brand=a;
this.model=b;
this.price=c;
this.warranty=d;
}
public String getBrand(){
return brand;
}
public String getModel(){
return model;
}
public double getPrice(){
return price;
}
public int getWarranty(){
return warranty;
}
public String toString(){
return "\n\nBrand: "+brand +"\nModel: "+ model +"\nPrice: $"+ price +"\nWarranty: "+ warranty;
}
}
public class LinkedList
{
private Node first;
private Node last;
private Node current;
public LinkedList()
{
first = null;
last = null;
current = null;
}
public boolean isEmpty(){
return (first == null); }
public void insertAtFront(Object insertItem){
Node newNode = new Node(insertItem);
if (isEmpty()){
first = newNode;
last = newNode;
}else{
newNode.next = first;
first = newNode;
}
}
public void insertAtBack(Object insertItem){
Node newNode = new Node(insertItem);
if(isEmpty()){
first = newNode;
last = newNode;
}else{
last.next = newNode;
last = newNode;
}
}
public Object removeFromFront(){
Object removeItem = null;
if(isEmpty()){
return removeItem;
}
removeItem = first.data;
if(first == last){
first = null;
last = null;
}else
first = first.next;
return removeItem;
}
public Object removeFromBack(){
Object removeItem = null;
if(isEmpty())
{
return removeItem;
}
removeItem = last.data;
if (first == last)
{
first = null;
last = null;
}else{
current = first;
while(current.next != last)
current = current.next;
last = current;
last.next = null;
}
return removeItem;
}
public Object getFirst(){
if(isEmpty())
return null;
else
{
current = first;
return current.data;
}
}
public Object getNext(){
if(current == last)
return null;
else
{
current = current.next;
return current.data;
}
}
}
As I said before, I can print all the details of the phones, but how to really use it as conditions, like If-else statement? for example, if(obj.getBrand().equalsIgnoreCase("Nokia")){} , I can achieve this with ArrayList but since this is LinkedList task, So I'm still figuring this out without even know if its possible or not. I hope someone would understand this and able to help. TQ
here's my node code for the LinkedList
public class Node {
Object data;
Node next;
Node(Object obj){
data=obj;
}
}
You should iterate using while and validating if the list has ended.
Diferently from an ArrayList, that you can directly acess the vector positions, in a linked list you should walk from node to node. Also, in your example you only implement a getNext() method and not a get(i).
Example:
Object aux = linkedList.getFirst();
while(aux != null) {
// your business logic here
aux = linkedList.getNext();
}
As you dont make the use of generics in your implementation, to acess your object data, you will need to use cast or make use of generics in your implementation.
Cast way:
while(aux != null) {
phoneObject = (Smartphone) aux;
// your business logic here
if(phoneObject.getBrand().equalsIgnoreCase("Nokia")){
System.out.println("Phone brand == Nokia");
}
aux = linkedList.getNext();
}
In the generic approach, you will also need to change the LinkedList implementation and Node implementation.
LinkedList:
public class LinkedList<T>
{
private Node<T> first;
private Node<T> last;
private Node<T> current;
public T getFirst(){
if(isEmpty())
return null;
else
{
current = first;
return current.data;
}
}
public T getNext(){
if(current == last)
return null;
else
{
current = current.next;
return current.data;
}
}
// add other methods here
}
Node:
public class Node<T> {
T data;
Node<T> next;
// add other methods here
}
Main:
LinkedList<Smartphone> linkedList = new LinkedList<Smartphone>();
// add objects
Smartphone aux = linkedList.getFirst();
while(aux != null) {
// no need to cast, because of generics use
if(aux.getBrand().equalsIgnoreCase("Nokia")){
System.out.println("Phone brand == Nokia");
}
// your business logic here
aux = linkedList.getNext();
}
Your getNext() method, returns null if your list has ended, so our stop criteria is aux == null. Our loop will execute while aux is not null, execute all your business logic (if clauses or what ever validation you want to do) and in the end of the loop, you will set the next object to aux variable.
You should add a generic parameter to your LinkedList.
class LinkedList<T> {
private Node<T> first;
private Node<T> last;
private Node<T> current;
....
}
class Node<T> {
T data;
Node<T> next;
Node(T obj) {
data = obj;
}
}
Then you can only add objects of that type to your list.
LinkedList<Smartphone> phoneList = new LinkedList<>();
But of course, if you can you really should not implement LinkedList by yourself but use the existing one! That's far more easier and safer to use.
List<Smartphone> nokiaList = new ArrayList<>();
List<Smartphone> phoneList = new LinkedList<>();
//input
phoneList.add(new Smartphone("Nokia", "Nokia 7 Plus", 1300, 260101));
phoneList.add(new Smartphone("Samsung", "Galaxy S8", 900, 220100));
phoneList.add(new Smartphone("Xiaomi", "Mi 10", 1500, 150031));
phoneList.add(new Smartphone("Nokia", "3310", 250, 101001));
phoneList.add(new Smartphone("Samsung", "Galaxy Y", 400, 774101));
phoneList.add(new Smartphone("Apple", "iPhone 7", 1100, 316300));
//The conditions
//If nokia + the price $1200+, it will save all the info about nokia
//If brand samsung + model Galaxy Y, It will count the total of the phone
Object obj;
int countSamsung = 0;
for (int i = 0; i < phoneList.size(); i++) {
Smartphone phone = phoneList.get(i);
if (phone.getBrand().equalsIgnoreCase("Nokia")) {
nokiaList.add(phone);
}
if (phone.getBrand().equalsIgnoreCase("Samsung")) {
if (phone.getModel().equalsIgnoreCase("Galaxy Y")) {
countSamsung++;
}
}
}

Is it possible to use 2 Data Type in an Custom ADT(Sorted Linked List)?

I am trying to do a Leaderboard for a game by using a Sorted Linked List. I was able to do so by sorting the point in descending order which mean higher point to lower point. Moreover, I will also need to put player name together with the point. The problem comes here. The SLL(Sorted Linked List) I implemented is an Integer data type, it works perfectly with the Integer data type as it sorted the numbers.
SortedListInterface<Integer> Player = new LeaderboardSortedLinkedList<Integer>();
But when I trying to put the player name which used String, it won't be able to do so because the point data type will need to follow the player name's data type.
Below are the codes of the driver class:
public class testLeaderboard {
public static void main(String[] args) {
SortedListInterface<Integer> Player = new LeaderboardSortedLinkedList<Integer>();
Player.add(1000000);
Player.add(500000);
Player.add(250000);
Player.add(125000);
Player.add(64000);
Player.add(32000);
Player.add(16000);
Player.add(8000);
Player.add(4000);
Player.add(2000);
Player.add(1000);
Player.add(500);
Player.add(300);
Player.add(200);
Player.add(100);
System.out.printf("=================================\n"
+ " Leaderboard\n"
+"=================================\n");
for(int i=0; i< Player.size();i++){
System.out.printf("%3d. %s\n",(i+1), Player.get(i+1));
}
}
}
Here is the Entity class
public class Player {
private String name;
private int prize;
public Player(String name, int prize) {
this.name = name;
this.prize = prize;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrize() {
return prize;
}
public void setPrize(int prize) {
this.prize = prize;
}
#Override
public String toString() {
return "Player{" + "name=" + name + ", prize=" + prize + '}';
}
}
Here's the custom Sorted Lineked List
public class LeaderboardSortedLinkedList<T extends Comparable<T>> implements SortedListInterface<T> {
private Node firstNode;
private int length;
public LeaderboardSortedLinkedList() {
firstNode = null;
length = 0;
}
public boolean add(T newEntry) {
Node newNode = new Node(newEntry);
Node nodeBefore = null;
Node currentNode = firstNode;
while (currentNode != null && newEntry.compareTo(currentNode.data) < 0) {
nodeBefore = currentNode;
currentNode = currentNode.next;
}
if (isEmpty() || (nodeBefore == null)) { // CASE 1: add at beginning
newNode.next = firstNode;
firstNode = newNode;
} else { // CASE 2: add in the middle or at the end, i.e. after nodeBefore
newNode.next = currentNode;
nodeBefore.next = newNode;
}
length++;
return true;
}
public boolean contains(T anEntry) {
boolean found = false;
Node tempNode = firstNode;
int pos = 1;
while (!found && (tempNode != null)) {
if (anEntry.compareTo(tempNode.data) <= 0) {
found = true;
} else {
tempNode = tempNode.next;
pos++;
}
}
if (tempNode != null && tempNode.data.equals(anEntry)) {
return true;
} else {
return false;
}
}
public int size(){
int count = 0;
//Node current will point to head
Node current = firstNode;
while(current != null) {
//Increment the count by 1 for each node
count++;
current = current.next;
}
return count;
}
public T get(int position){
T result = null;
if ((position >= 1) && (position <= length)) {
Node currentNode = firstNode;
for (int i = 0; i < position - 1; ++i) {
currentNode = currentNode.next; // advance currentNode to next node
}
result = currentNode.data; // currentNode is pointing to the node at givenPosition
}
return result;
}
public final void clear() {
firstNode = null;
length = 0;
}
public int getLength() {
return length;
}
public boolean isEmpty() {
return (length == 0);
}
public String toString() {
String outputStr = "";
Node currentNode = firstNode;
while (currentNode != null) {
outputStr += currentNode.data + "\n";;
currentNode = currentNode.next;
}
return outputStr;
}
private class Node {
private T data;
private Node next;
private Node(T data) {
this.data = data;
next = null;
}
private Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
}
And the results is here
=================================
Leaderboard
=================================
1. 1000000
2. 500000
3. 250000
4. 125000
5. 64000
6. 32000
7. 16000
8. 8000
9. 4000
10. 2000
11. 1000
12. 500
13. 300
14. 200
15. 100
Here's my testing on the point with string data type because I can't think a way to use player name and point with 2 different data types at the same time in my custom ADT.
public class testLeaderboard {
public static void main(String[] args) {
SortedListInterface<String> Player = new LeaderboardSortedLinkedList<String>()
Player.add("1000000");
Player.add("500000");
Player.add("250000");
Player.add("125000");
Player.add("64000");
Player.add("32000");
Player.add("16000");
Player.add("8000");
Player.add("4000");
Player.add("2000");
Player.add("1000");
Player.add("500");
Player.add("300");
Player.add("200");
Player.add("100");
System.out.println(Player);
}
And here's the result that it compare the first letter of the string.
8000
64000
500000
500
4000
32000
300
250000
2000
200
16000
125000
1000000
1000
100
Is there anyway to use both String and Integer in one ADT because if i couldn't do so, I won't be able sort the point. I'm so sorry for the long question. I am very new to data structures and algorithms so I really need some help on this. Much appreciate.
To keep the points and names together, you need to add Player objects into the list as they are, not just their points or their names:
SortedListInterface<Player> players = new LeaderboardSortedLinkedList<>();
players.add(new Player("Alpha", 1000000));
players.add(new Player("Beta", 500000));
players.add(new Player("Gamma", 250000));
For this to work, you will need to be able to compare Player objects by their point numbers. You do that by implementing the Comparable interface and adding a compareTo method.
You'll also want to add a toString() method, so that you can print a Player object.
public class Player implements Comparable<Player> {
private String name;
private int prize;
#Override
public int compareTo(Player other) {
return Integer.compare(this.prize, other.prize);
}
#Override
public String toString() {
return String.format("name='%s' prize=%d", name, prize);
}
}
Thank You for helping me I successfully get the output I want. But got a little problem which is this
=================================
Leaderboard
=================================
1. name='Alpha' prize=1000000
2. name='Beta' prize=500000
3. name='Gamma' prize=250000
BUILD SUCCESSFUL (total time: 1 second)
It print the output at this way [name="Alpha"]. Im not sure what is the problem but i guess it's my System.out.print code.
System.out.printf("%3d. %s\n",(i+1), players.get(i+1));
and here's my .get() function.
public T get(int position){
T result = null;
if ((position >= 1) && (position <= length)) {
Node currentNode = firstNode;
for (int i = 0; i < position - 1; ++i) {
currentNode = currentNode.next; // advance currentNode to next node
}
result = currentNode.data; // currentNode is pointing to the node at givenPosition
}
return result;
}

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");

Sorted Linked Based List Java

I'm working on an assignment for my Data Structures class. We have to create an address book using our own sorted linked based list adt. Right now the add method works, but it seems to make all the nodes point to the first node. Whenever I try to output the the list using getEntry() in a for loop, it gives me the last added entry each time. I've tried using toArray but it does the same thing. Can you see any problems?
public class GTSortedLinkedBasedList implements GTListADTInterface {
private Node firstNode;
private int numberOfEntries;
public GTSortedLinkedBasedList(){
//firstNode = new Node(null);
numberOfEntries = 0;
}
public void setNumberOfEntries(int x){
numberOfEntries = x;
}
public void add(ExtPersonType newEntry){
//firstNode = null;
Node newNode = new Node(newEntry);
Node nodeBefore = getNodeBefore(newEntry);
if (isEmpty() || (nodeBefore == null))
{
// Add at beginning
newNode.setNextNode(firstNode);
firstNode = newNode;
}
else
{
// Add after nodeBefore
Node nodeAfter = nodeBefore.getNextNode();
newNode.setNextNode(nodeAfter);
nodeBefore.setNextNode(newNode);
} // end if
numberOfEntries++;
}
private Node getNodeBefore(ExtPersonType anEntry){
Node currentNode = getFirstNode();
Node nodeBefore = null;
while ((currentNode != null) &&
(anEntry.getFirstName().compareTo(currentNode.getData().getFirstName()) > 0))
{
nodeBefore = currentNode;
currentNode = currentNode.getNextNode();
} // end while
return nodeBefore;
}
private class Node {
private ExtPersonType data;
private Node next;
public Node(ExtPersonType dataValue) {
next = null;
data = dataValue;
}
public Node(ExtPersonType dataValue, Node nextValue) {
next = nextValue;
data = dataValue;
}
public ExtPersonType getData(){
return data;
}
public void setData(ExtPersonType newData){
data = newData;
}
public Node getNextNode(){
return next;
}
public void setNextNode(Node newNode){
next = newNode;
}
}
public ExtPersonType getEntry(int givenPosition) {
if ((givenPosition >= 1) && (givenPosition <= numberOfEntries)){
assert !isEmpty();
return getNodeAt(givenPosition).getData();
}
else{
throw new IndexOutOfBoundsException("Illegal position given to getEntry operation.");
}
}
public void loadData(GTSortedLinkedBasedList contacts) throws FileNotFoundException{
//int index = 0;
ExtPersonType person = new ExtPersonType();
DateType tempDate = new DateType();
AddressType tempAddress = new AddressType();
Scanner file = new Scanner(new FileInputStream("Programming Assignment 1 Data.txt"));
while(file.hasNext()){
person.setFirstName(file.next());
person.setLastName(file.next());
tempDate.setMonth(file.nextInt());
tempDate.setDay(file.nextInt());
tempDate.setYear(file.nextInt());
person.setDOB(tempDate);
tempAddress.setStreetAddress(file.nextLine());
if(tempAddress.getStreetAddress().isEmpty()){
tempAddress.setStreetAddress(file.nextLine());
}
tempAddress.setCity(file.nextLine());
tempAddress.setState(file.nextLine());
tempAddress.setZipCode(file.nextLine());
person.setAddress(tempAddress);
person.setPhoneNumber(file.nextLine());
person.setPersonStatus(file.nextLine());
if(person.getPersonStatus().isEmpty()){
person.setPersonStatus(file.nextLine());
}
contacts.add(person);
System.out.println(contacts.getEntry(contacts.getLength()).getFirstName());
//index++;
}
}
public static void main(String[] args) throws FileNotFoundException {
AddressBook ab = new AddressBook();
ab.loadData(ab);
ExtPersonType people = new ExtPersonType();
//people = ab.toArray(people);
System.out.println(ab.getLength());
for(int cnt = 1; cnt <= ab.getLength(); cnt++){
people = ab.getEntry(cnt);
System.out.println(people.getFirstName());
}
}
EDIT: The add method is overwriting each previous object with the newly added one. It also doesn't seem to matter if I do a sorted list or just a basic list.
I'm not going to lie here, I'm not totally sure I understand your code but I think I see what's wrong. In your getNodeBefore() method's code, you set currentNode() always to firstNode(). I believe that is causing the problem. I see that you are trying to recursively move through the list to find the proper node but I don't think each recursive call is causing movement through the list. I suggest you add properties to the object that represent the forward and backward nodes.
Something like this...
private T data;
private Node nodeBefore;
private Node nodeAfter;
As you create objects, you assign the properties before and after and then all the information you need is contained in the object itself.
To move recursively through the list you would then just add a statement like currentNode = currentNode.nodeAfter.
Your getNodeBefore() method would simply return currentNode.nodeBefore and getNodeAfter() would return currentNode.nodeAfter.
You don't have code that handles the situation where the node being added will be the first node in the list, but the list is also not empty. In this case, getNodeBefore returns null, and your code overwrites the root node.
Try
if (isEmpty() && (nodeBefore == null))
{
// Add at beginning
newNode.setNextNode(firstNode);
firstNode = newNode;
}
else if(nodeBefore == null)
{
Node temp = new Node();
temp.setNextNode(first.next);
temp.setData(first.data);
newNode.setNextNode(temp);
firstNode = newNode;
}

Converting a Single Linked List to a Double Linked List

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/

Categories