Assistance with creating java Linked Lists using only nodes - java

been working on this project for a while now with Java. It was recommended that I use a Linked List or an Array List for my program, which makes perfect sense. However, the professor says we must make and use our own Linked List utilizing Nodes. Despite a bit of research and asking around in class, working with Nodes has got me very confused. I'm sure it's something simple I am missing, but I am at a complete loss right now. Here is the class in which the List is stored (I think). It is titled Aircraft because we are creating a list to store multiple aircraft and some details associated with them (name of flight, speed, altitude, type of plane). I have a Main class (not listed) which the user interacts with - I've got that class pretty much taken care of.
package airTraffic;
public class Aircraft {
public static String name;
public static String type;
public static int speed;
public static int alt;
Aircraft nextCraft;
public Aircraft (String n, String t, int s, int a) {
name = n;
type = t;
speed = s;
alt = a;
}
public Aircraft() {
}
public static void setName(String n) {
name = n;
}
public static String getName (String lookUp) {
return name;
}
public static void removeName () {
//remove the flight - not sure what to place here
}
public static void setType (String t) {
type = t;
}
public static String getType () {
return type;
}
public static void setSpeed (int s) {
speed = s;
}
public static int getSpeed () {
return speed;
}
public static void setAlt(int a) {
alt = a;
}
public static int getAlt () {
return alt;
}
public Aircraft next = null;
//auto generated method from ATControl
public static void add(String s) {
}
//auto generated methods from ATControl - what goes here???
public static void remove() {
}
public Object getNext() {
// TODO Auto-generated method stub
return null;
}
public void setNext(Object next2) {
// TODO Auto-generated method stub
}
}
Below, I have what I believe to be the class in which the Nodes are created and stored. This is where I am very confused and think I have it wrong. I am not sure how to call upon a node to actually add and store data to it. I will also need to be able to get the node (via the flight name) and remove the node (via the flight name)
package airTraffic;
import java.util.*;
import airTraffic.Aircraft;
public class ATControl {
static Main m = new Main ();
Aircraft aircraft = new Aircraft ();
//declare node names for list
public static Aircraft head = new Aircraft ();
public static Aircraft tail = new Aircraft ();
// stores data
private static final int INITIAL_ALLOCATION = 20;
private static int size = INITIAL_ALLOCATION;
// tells list to add nodes
public static void Nodes (String s, int n) {
n = size;
head.next = tail;
tail.next = tail;
Aircraft temp = head;
for (int i= 0; i < size; ++i) {
temp.next = new Aircraft ();
temp = temp.next;
}
temp.next = tail;
}
public static void addNodes (int n) {
n = size;
Aircraft temp = new Aircraft ();
Aircraft current = head;
for (int i = 1; i < n && current.getNext() != null; i++) {
current = (Aircraft) current.getNext();
temp.setNext(current.getNext());
current.setNext (temp);
size++;
}
}
//add plane and details
public static void addToList (Scanner in) {
// should add new aircraft to new node on linked list
System.out.printf("Enter flight number: ");
String add = in.next();
Aircraft.setName (add);
ATControl.addNodes (Integer.parseInt(add));
//type of plane
System.out.printf("Enter type of plane: ");
String plane = in.next();
Aircraft.setType (plane);
//plane speed
System.out.printf("Enter current speed: ");
int speed = in.nextInt();
Aircraft.setSpeed (speed);
ATControl.addNodes (Integer.parseInt(add));
//add Altitude
System.out.printf("Enter current altitude: ");
int alt = in.nextInt();
Aircraft.setAlt(alt);
ATControl.addNodes (Integer.parseInt(add)); // I am fairly certain this is wrong
}
//show flight
public static void showFlight (Scanner in) {
System.out.printf("Enter flight number for details: ");
String lookUp = in.next();
Aircraft.getName(lookUp);
}
// display all flights
public static void displayAll (Scanner in) {
System.out.printf("All flights: " );
}
//remove flight
public static void removeFlight (Scanner in) {
System.out.printf("Enter flight number to be removed: ");
}
}

You are getting close. First of all a linked list is a list of objects, commonly called nodes, each of which has one or more links to other objects. In your case the nodes are Aircraft.
This should help you a bit: Wikipedia:Linked List
Your main problem so far is that you do not have links in your Aircraft class. Since this is a linked list you need to include the reference to the next element in the list. Within the Aircraft class you should have a property called next of type Aircraft that links you to the next Aircraft in your list. This allows you to call myAircraft.next, as you are in your code so far, which will allow you to travel down the list in order. I'll leave you to figure out the rest yourself, this is homework, but feel free to comment if you need any more explanation.

I think you are pretty close - but it's hard to tell exactly what's going on in your ATControl class. Typically the add method on a linked list takes a node (in your case an Aircraft), not a number.
The key to a linked list is that each node has a pointer to the next one in the list. In your Aircraft class, you have: Aircraft next, which will serve as that pointer.
I would suggest implementing the following methods in ATControl:
public static Aircraft getUserInput(Scanner in)
{
Aircraft aircraft = new Aircraft();
// get your values from the user and set them in your new aircraft
return aircraft;
}
public static void add(Aircraft aircraft)
{
// starting at head, walk through the list (repeatedly call next on
// the current Aircraft) until you reach the desired position
Aircraft temp = head;
while (temp != null) // ...
}
public static void remove(String flightNum)
{
// again, the same way you did in add, walk through the list until you find it
if (current.getName().equals(flightNum))
// we found it, so remove it
}

Unless you have a very firm grasp on OOP and reference types, attempting to write a LinkedList implementation is a practice in masochism.
The following is going to be long and possibly painful/humiliating. That's OK, it'll be a good learning experience. I'm putting a lot of effort into this to provide a complete implementation with thorough commenting. I suggest you read the details closely until you fully understand their purpose.
First, fix your Aircraft class. Since you'll need to create multiple instances, static members won't work. If you don't understand why, take some time to brush up on your OOP fundamentals.
List nodes should be designed to store minimal data. In your case it looks like you're most of the way there. There is flight data specific to each node and a reference to the next item in the list. That's all you need.
Without all the extra cruft here's what it looks like:
public class Aircraft {
public String name;
public String type;
public int speed;
public int alt;
Aircraft next;
public Aircraft (String n, String t, int s, int a) {
name = n;
type = t;
speed = s;
alt = a;
next = null;
}
}
Looking good. It's safe to assume that this has all of the necessary functionality built-in.
Feel free to add the following back in if you want:
setName()
getName()
setType()
getType()
setSpeed()
getSpeed()
setAlt()
getAlt()
Note: These will only work if they're not set to static. Unless you plan to pass the Aircraft instance being changed in as one of the arguments every time you call it. Trust me, using instance methods is a lot easier.
Changes:
I removed the Aircraft() constructor. At a minimum, you'll need to initialize an Aircraft node with at least a flight number (or some other unique identifier) or you won't be able to find the Aircraft in the list later.
removeName() is useless. Since the individual nodes are only aware of the next item in the list they are incapable of removing themselves. If you used a doubly-linked-list where each node stores references to both the previous and next nodes then it would be possible but there really is no need. Same goes for the add() and remove()* methods. Additions/removals are handled in the **ATControl class.
There's not much need for getNext() or setNext() either. Since ATControl is used to maintain state of the list (ex size, capacity, etc) you won't want to make nextCraft publicly accessible via getters/setters.
Now for ATControl:
public class ATControl {
private Aircraft head; // stores the start of the chain
private Aircraft tail; // stores the end of the chain
private int size; // stores the length of the chain
public ATControl() {
// ♫ "Started from the bottom now we're herre' ♫
// Seriously, the list should start with nothing
head = null;
tail = null;
size = 0;
}
public void addFlight(String flight, String plane, int speed, int alt) {
// TODO: Implement this
}
public void removeFlight(String name) {
// TODO: Implement this
}
public void displayFlight(String name) {
// TODO: Use a foreach loop to find and display a flight
}
public void displayAll() {
// TODO: Use a foreach loop to display the flights here
}
}
Changes:
I removed the main* member because I don't have the slightest idea how it works here. Either way, to use this you'll need to create a new **ATControl instance.
I removed the inline variable declarations because that's instance members have to be set in the constructor.
The head and tail are initialized to null because no Aircraft have been added yet.
I removed the aircraft member because it will never be used.
Unless you only expect to create one ATControl instance, you shouldn't set head and tail too static either. If either of them are changed by anything but ATControl, it'll screw up the internal state of the list so they should be set to private.
I removed the size constraint because it's not necessary to make this work. You can add it back in later if you want.
I axed Nodes() and addNodes() for two reasons. First, it both violate the SRP (Single Responsibility Principle) because they are responsible for creating a node and a collection of nodes. Second -- I'm assuming it's a bug but -- you were passing in the flight number as the number of nodes you wanted to create. Ex, if the flight number were 1457 you'd be adding 1457 empty nodes to the list.
I renamed addToList() to addFlight() to keep things consistent. I also renamed showFlight() to displayFlight() for consistency. For the sake of simplicity and to make this class useful to more than just command-line inputs I also removed the user input parts.
I know, I know! I'm a merciless butcher but now the code is in a good position to start building in the necessary functionality.
First things first. If you don't know to make a class iterable (ie work as a foreach loop) you're about to find out. I'll need to add some more stuff to ATControl but it'll be fun.
public class ATControl implements Iterable {
private Aircraft head;
private Aircraft tail;
private int size;
public ATControl() {
head = null;
tail = null;
size = 0;
}
public void addFlight(String flight, String plane, int speed, int alt) {
// if the list is not currently empty
if (!isEmpty()) {
// store a reference to the last Aircraft in the list
Aircraft prev = tail;
// create a new aircraft and add it to the end of the list
tail = new Aircraft(flight, plane, speed, alt);
// link the old tail to the new tail
prev.next = tail;
}
// an empty list needs to be handled a little differently
else {
// notice, with no tail there's no tail to update
tail = new Aircraft(flight, plane, speed, alt);
// also, since there's only one item the head and tail are the same
head = tail;
}
size++;
}
// The hard part. Lots of nasty edge cases.
// Creating one of these from scratch will make your head hurt.
// Note: Setting variables to null marks them for the garbage collector.
// SideNote: With a doubly-linked list you can do removals within a foreach loop
public void removeFlight(String flight) {
Node prev = head;
Node curr = head;
// crawl the list looking for a match
while (curr.next != null || curr == tail) {
if (curr.flight.equals(flight)) {
// if there is only one item left, null everything
if (size == 1) { head = null; tail = null; }
// reset the head to start at the second Aircraft
else if (curr.equals(head)) { head = head.next; }
// reset the tail to end at the 2nd-to-last Aircraft
else if (curr.equals(tail)) { tail = prev; tail.next = null; }
// if it's in the middle, re-connect the broken links on either end
else { prev.next = curr.next; }
size--;
break;
}
prev = curr;
curr = prev.next;
}
}
public boolean isEmpty() {
return size == 0; // only returns true if size is 0
// The fun part. The following are necessary to make the list iterable
// Like magic, this class will now be callable as a foreach loop
public Iterator<Aircraft> iterator() { return new ATCIterator(); }
// This iterator code can be reused on any linked-list implementation
// Keep this handy in case you need to implement Iterable in the future
private class ATCIterator implements Iterator<Aircraft> {
private Aircraft current = head;
public Aircraft next() {
if (!hasNext()) { throw new NoSuchElementException(); }
Aircraft aircraft = current;
current = current.next;
return aircraft;
}
public boolean hasNext() { return current != null; }
// inline removals require a doubly linked list. To reconnect the break
// in the chain the node has to be aware of both the previous and next nodes.
public void remove() { throw new UnsupportedOperationException(); }
}
// lets put that foreach loop functionality to good use now.
// Bonus: use this to retrieve the matching Aircraft instance
// Once you have a reference to the Aircraft instance you can do things like
// get/set it's internal values.
public aircraft getFlight(String flight) {
for (Aircraft aircraft : this)
if (this.flight == flight) {
return this;
}
// displays the flight number of the first match
public void displayFlight(String flight) {
for (Aircraft aircraft : this)
if (this.flight == flight) {
System.out.printf("Flight: " + flight);
// Note: you can access the Aircraft details here via the 'this' keyword
return;
}
// crawls the whole list and displays the flight number of every aircraft
public void displayAll() {
for (Aircraft aircraft : this)
System.out.printf("Flight: " + flight);
// Note: you can access the flight details here via the 'this' keyword
}
}
So, you have a wall of code with lots of comments to chomp on. Time for some theory.
What makes a LinkedList a LinkedList anyway?
It's literally just a bunch of object instances that are randomly placed on the heap and linked together via references (or pointers for the C crowd).
Imagine a LinkedList as a Samba Line.
Source: The Traveling Eye Blog
Note: A doubly-linked list is the same except the line can change directions.
Every person is holding on to the person in front of them but they can't see who is behind them. Adding to a list is like adding a person to the front of the line. Technically, the LinkedList I wrote works in the opposite direction with additions being added to the front and removals being cut from the tail but the concept is the same.
Fetching/removing an item from the list is like adding a limbo pole. The first hit gets taken out of the chain and the break is mended by reconnecting the ends of the break.
The benefit to using a LinkedList is that it can be as big or as small as you want. You're free to add/remove nodes however you want.
The downside is, unlike an array there's no way to fetch an item from within the list without first walking the chain of links. Also, the overhead of all those class instances and references starts to get expensive when the list grows very large.
In performance terms it takes O(1) (ie constant time) to add items. O(N) (ie linear time) to fetch/remove items from the list. And, depending on whether the list is single/double and/or jump linked there is a notable memory overhead involved.
There are other data structures like ArrayLists, HashMaps, etc that have better performance or memory characteristics for use cases like yours but they're even more complicated to write/manage.
The easiest way to get all the magical goodness of a high-level data structures without the work is to wrap and extend an existing implementation. For example, you could create a class that uses an ArrayList internally for data storage. You can even make it iterable using the methods I demonstrated above. Except, instead of being written for any generic type it can be customized to work use your Aircraft data type.
Note: If you want to learn how to write data structures I suggest you take an Algorithms I class online (or otherwise).

Here is a link to what the re ponders are referring to when they say a list. Here is a link http://www.algolist.net/Data_structures/Singly-linked_list/Traversal that explains list. However, I'm not sure this is representative in java. The code you wrote looks like you are not sorting but adding all airplanes at the end of the list. Therefore the list is not sorted. When you make temp.next = tail is making the last airplane in the list point to itself rather than null. But you aren't checking for null you are counting the number of planes in the list. I posted a java example, where you have a node class with a node next, you should add node tail as well since your code is using it.

public class Node {
public int item;
public Node next;
public Node tail;
Node() {
item = 0;
next = null;
tail = null ;
}
Add Node(node tail, node new) {
tail.next = new;
tail.tail = new
new.tail =null
}
};
I hope I didn't make it worse. Good luck.
airplane class can extend the node class. Look at the childfactory class in java. It will give you an example of the type of methods you will use in the node class. Rethink your classes. Maybe remove Airplane will be a method in the node class like remove node. Anything that works on the node such as insert or add new, delete, and sort can be added to the node class. You can then reuse this class as you add more classes.
http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

Related

How can I inverse a list of elements if I can only access to an element and his next one?

I have been given a "class" called LinkedList which has only one atributte
"Node first" which refers to the first element of a list. The way to access the other ones is that class "Node" has access to an element 'x' and his following one:
public class LinkedList<T> {
private static class Node<E> {
E elem;
Node<E> next;
Node (E elem) {
this.elem = elem;
this.next = null;
}
}
private Node<T> first;
So that, I have been ordered to do a method called "reverse" from class "LinkedList" which has to reverse the list. However, the difficulty of the exercise is that I can only re-link the attributte "first", I mean I cannot create auxiliar data structures and that type of help.
I have done this in order to achieve the last element of the list, but I dont know how to continue:
public void reverse () {
Node<T> aux = first.next;
while (aux.next != null) {
first.elem = aux.elem;
aux = aux.next;
}
first.elem = aux.elem;
}
It seems quite a theoretical question to me, so you might want to check Geek for Geeks first. Most of these questions that are used in programming courses are well explained there, including coding examples.
In this case, a well-known solution is to use three pointers: a current number, the previous number , and the next number; to keep track of nodes to update reverse links.
Check here: https://www.geeksforgeeks.org/reverse-a-linked-list/

Assign "this" to a reference variable in Java

I'm trying to used recursive method to complete the addLast method in a singly linked list, however, the code gives me a wrong output of list.size() = 2 and list.getFirst() = 5. The reason should be due to the line
SLList p=this;
It seems changing p reference changes "this" reference as well, which is not so logic to me. Could anyone give some details about this? Thx
public class SLList {
public class IntNode {
public int item;
public IntNode next;
public IntNode(int i, IntNode n) {
item = i;
next = n;
}
}
private IntNode first;
public SLList(int x) {
first = new IntNode(x, null);
}
/** Adds an item to the front of the list. */
public void addFirst(int x) {
first = new IntNode(x, first);
}
/** Retrieves the front item from the list. */
public int getFirst() {
return first.item;
}
/** Adds an item to the end of the list. */
public void addLast(int x) {
SLList p = this;
if (p.first. next == null) {
p.first.next = new IntNode (x, null);
}
else {
p.first = p.first.next;
p.addLast(x);
}
}
/** Returns the number of items in the list using recursion. */
public int size() {
/* Your Code Here! */
SLList p = this;
if (p.first == null) {
return 0;
}
else if (p.first.next == null){
return 1;
}
else {
p.first = p.first.next;
return 1 + p.size();
}
}
public static void main (String[] args) {
SLList list=new SLList (5);
list.addFirst(10);
list.addFirst(15);
list.addLast(17);
System.out.println(list.getFirst());
System.out.println(list.size());
}
}
The problem is nothing to do with the assignment of this. Nothing can change this. Period.
(But things can change the state of the object that this refers to.)
The real problem is in your implementation of the size method. Your size method is causing the list to change. It shouldn't. In your case, the change causes:
the size() method to return the wrong value
subsequent getFirst() calls to return the wrong value.
I won't say exactly where the bug, but you should be able to spot it yourself by a process of elimination. (Or if that fails, use a debugger and try to observe where the list is changing.)
There are bigger problems with your algorithms than you think. size() is incorrect. You can fix this if you realize that you need to count the number of IntNode objects in the list. Similarly all other methods need to manipulate IntNode objects.
SLList p = this;
p reference to the same SLList object. if you make any changes to 'p' then it will also happened to 'this', becuase of reference type (not value type).
Here in the statement
p.first = p.first.next;
the reference to the first is changed when you call 'addLast' method. You loss the reference to the first item.
If you remove the line
list.addLast(17);
in main method you will see the correct answer. The problem is with this method.
Change the method as follow and add the new method below.
/** Adds an item to the end of the list. */
public void addLast(int x) {
addLast(x, this.first);
}
private void addLast(int x, IntNode node){
if(node.next == null){
node.next = new IntNode (x, null);
}else {
node = node.next;
addLast(x, node);
}
}
Then you will not lose the reference to first item and now it works fine,
Problem in your implementation is addLast and size method are changing the value of field variable first.
It don't matter whether you assignthis to some variable or use directly.
Because assigning this to some variable does not create new this object but assign's reference to that variable.
So you should first copy value of first field variable to some local variable then iterate on it.In this way your first will not change.
Hint: Don't change the first variable reference.
Your addLast() and size() changes value of first which is wrong.
Problem is in this line.
p.first = p.first.next;

Coding conventions for Linked Lists

I have been implementing this interview question in Java . A fairly simple problem with an additional constraint of size :
Find the Nth Node from the end of a Linked List where the size of the Linked List is unknown?
I am not concerned with the solution to this problem,because I have already figured that out.
Instead, I want to know whether my implementation maintains the coding conventions which experienced coders maintain while coding a problem related to Linked Lists and it's implementation?.Here is my implementation of the above problem:
import java.io.*;
class NthNodeFromEnd<AnyType>
{
private Node<AnyType> head;
private Node<AnyType> pointer;
private class Node<AnyType>
{
protected AnyType item;
protected Node<AnyType> next;
}
void push(AnyType item)
{
if(isEmpty())
{
head = new Node<AnyType>();
head.item = item;
head.next = null;
pointer = head;
}
else
{
Node<AnyType> newNode = new Node<AnyType>();
newNode.item = item;
newNode.next = null;
pointer.next = newNode;
pointer = pointer.next;
}
}
boolean isEmpty()
{
return head == null;
}
AnyType printNthLastNode(int n)
{
Node<AnyType> ptr1 = head;
Node<AnyType> ptr2 = head;
for(int i =0;i<n;i++)
{
ptr1 = ptr1.next;
}
while(ptr1!=null)
{
ptr1 = ptr1.next;
ptr2 = ptr2.next;
}
return ptr2.item;
}
public static void main(String args[])
{
NthNodeFromEnd<Integer> obj = new NthNodeFromEnd<Integer>();
obj.push(1);
obj.push(2);
obj.push(3);
obj.push(4);
obj.push(5);
obj.push(6);
obj.push(7);
System.out.println("The nth item is = "+obj.printNthLastNode(5));
}
}
P.S. - I am aware of the fact that there is an inbuilt implementation of Linked List in Java, but I don't want to use that.I want to know whether this implementation of the problem is good enough or is there a better way to tackle Linked List related problems?
Regarding the code conventions:
generic types are typically defined as a single uppercase letter: E or T, but not AnyType, which looks like a concrete type.
operators should be surrounded by spaces, semi-colons followed by a space, etc. For example, for(int i =0;i<n;i++) should be for (int i = 0; i < n; i++)
A method printNthLastNode() should print the nth last node, not return it. A method returning it should be named getNthLastNode() or findNthLastNode(). BTW, this method doesn't return a node, but a value stored in the list.
methods should generally not be package-private. They should be public or private generally.
the usual convention in Java is to have opening curly braces at the end of the line, and not at the beginning of the next line.
your method printNthLastNode() will fail with a NPE if the list is empty or not large enough. A better exception type should be used to signal this problem.
the class should not import java.io.*, since it doesn't use any class from java.io. packages should generally not be imported. Classes should.
String[] args is more readable than String args[], and is more conventional.
the Node class should be static: it doesn't use any instance member of its enclosing type.
That said, the interviewer should see, with the code posted, that you understand how a linked list works and how pointers work, as well as generic types.

Building a linked list as the basis of a graph Null pointer errors

I am trying to build a graph based on a linked list, where I build the linked list of nodes, and each node points to a linked list of edges. I build the graph based on an input file.
My input file will be on the following scheme:
Number of Nodes in graph
SourceNode1 EndNode1
SourceNode2 EndNode2
....
For example:
4 //Number of nodes
1 2 //An edge between 1 and 2
1 3 //An edge between 1 and 3
2 4 //An edge between 2 and 4
An assumption is that the nodes in the graph will numbered 1 through the number of nodes and that no node will have more than 1 "parent" (though a node might have more than 1 "child").
My problem is trying to build the linked list containing the nodes. Each node has 3 fields: the edges coming from that node, the node value (1, 2, 3, etc.), and the next node (because is a linked list of nodes). I attempt to parse in the number of nodes, create a first node manually, and attach the rest of the nodes in an in an iterative fashion.
Note: The parent field is for some external analysis unrelated to this question. You can ignore it.
Node class:
public class Node {
private Edge firstEdge;
private Node parent;
private Node nextNode;
private int element;
//Constructor
public Node() {
parent = null;
firstEdge = null;
nextNode = null;
}
//Accsessor and Modifier Methods
public void setElement(int e) {element = e;}
public Node getNextNode() {return nextNode;}
public Edge getFirstEdge() {return firstEdge;}
public void setFirstEdge(Edge a) {firstEdge = a;}
public void setNextNode(Node a) {nextNode = a;}
public int getElement() {return element;}
public Node getParent() {return parent;}
public void setParent(Node p) {parent = p;}
//Checks for a non-null parent
public boolean hasParent() { return parent == null; }
//checks iff node has next edge
public boolean hasFirstEdge() { return firstEdge == null; }
//checks if a node has a next node
public boolean hasNextNode() { return nextNode == null; }
}
Edge class:
public class Edge {
//Instance Variables
private Node nextNode;
private Edge nextEdge;
//Constructor
public Edge() {
nextNode = null;
nextEdge = null;
}
//Accsessor and Modifier Methods
public void setNextNode(Node a) {nextNode = a;}
public void setNextEdge(Edge a) {nextEdge = a;}
public Node getNextNode() {return nextNode;}
public Edge getNextEdge() {return nextEdge;}
public boolean hasNextEdge() {
return nextEdge == null;
}
}
Driver class:
import java.util.Scanner;
import java.io.*;
public class Driver {
public static void main(String[] args)throws FileNotFoundException{
//Get text file for building the graph
Scanner console = new Scanner(System.in);
System.out.print("Please enter the text file name: ");
String fileName = console.nextLine();
Scanner in = new Scanner(new File(fileName));
//in contains the file reading scanner
int numNodes = in.nextInt(); //first line of the text file
Node first = new Node(); //first is head of the list
first.setElement(1);
int i = 2; //counter
//Build the nodes list; I get problems in this loop
while (i <= numNodes) {
Node head = new Node(); //Tracker node
head = first; //head is the first node of the list
/*Loop to end of the list*/
while(head.hasNextNode()) {
//Null check; without it, I get NullPointerExceptions.
//If it is not needed, or there is a better way, please inform me.
if (head.getNextNode() == null) {
break;
}
head = head.getNextNode(); //get to the end of the ilst
}
//Next node to add
Node newNode = new Node();
newNode.setElement(i); //Because of the 1, 2, 3 nature of the graph
head.setNextNode(newNode); //Set the last element as the next node
i++;
}
//Manually check if graph is made (check if the nodes are linked correctly)
System.out.println("First elem (expect 1): " + first.getElement());
System.out.println("Second elem (expect 2): " + first.getNextNode().getElement()); //It prints 4 here for some reason
System.out.println("Third elem (expect 3): " + first.getNextNode().getNextNode().getElement()); //Getting a NullPointerException
System.out.println("Fourth elem (expect 4): " + first.getNextNode().getNextNode().getNextNode().getElement());
System.out.println("Expecting null: " + first.getNextNode().getNextNode().getNextNode().getNextNode().getElement());
}
When I'm checking if the graph is built, I get problems. I am manually checking it (for this small graph, its possible), and simply print out the first node and the value of the subsequent nodes. I am expecting 1, 2, 3, 4, and null (for the element past 4, because it does not exist). The first node is fine, it prints 1. Calling first.getNextNode().getElement() prints 4, for some odd reason. And calling the node after that gives a NullPointerException. Could someone help me solve this problem?
Note: I haven't added the edges yet. I am just trying to get the core of the linked list of nodes built.
This is my first post on stack overflow. I apologize if it is vague, ambigous, overly detailed, lacking in information, or is a duplicate question. I could not find the answer anywhere else. All input is welcome and appreciated.
Much of your naming is very confusing and is in serious need of clarifying refactorization. Edge's nextNode should be called destinationNode or something along those lines to make it clear you are dereferencing from an Edge object instead of from another Node.
Now, let's delve into the actual implementation.
Node head = new Node(); //Tracker node
head = first; //head is the first node of the list
What's going on here? It looks like you set your local variable head to be a brand new Node; that's great. Except the very next line, you discard it and set it to the value of your first variable.
Then you traverse all the way to the end of the list with a while loop, then create another new Node (this one you actually use). (Normally if you wanted to add something to the end of the list you should be utilizing a doubly linked list, or should at least have pointers to both the first and the last elements... i.e., first always stays the same, but when you add a new node you simply say newNode = new Node(); last.nextNode = newNode; last = newNode; and then configure the new element from there. The way you are doing it, it's taking O(N^2) time to construct a singly-linked list with N elements, hardly ideal.
I also have some preferential criticism about the construction of your minor classes... if you are allowing values to be freely get and set to any value with public setters and getters without taking any action whatsoever when they change, you get the exact same functionality from simply marking those fields public and doing away with the getters and setters entirely. If you have any plans to add more functionality in the future it's fine the way it is, but if they are just going to be dumb linked list elements whose actual uses are implemented elsewhere then you are better off treating the class more like a struct.
Here's a good way to build a singly-linked Node list the way you're looking to:
int numNodes = in.nextInt(); //first line of the text file
// sentinel value indicating the beginning of the list
Node header = new Node();
header.setElement(-1);
// last node in the list
Node last = first;
// this loop constructs a singly linked ring from the header
for (int i = 1; i <= numNodes; i++) {
Node newNode = new Node();
newNode.setElement(i);
newNode.setNextNode(header);
last.setNextNode(newNode);
last = newNode;
}
// do your debug outputs here
// for instance, this loop always outputs every node in the list:
for (Node n = header.getNextNode(); n != header; n = n.getNextNode()) {
System.out.println("Node " + n.getElement());
}
Note that the use of header as a sentinel value guarantees that for any Node that's already been built, getNextNode() will never return null.
Again, all this code can be made much more readable by making the fields in your Node and Edge classes public and scrapping the getters and setters. header.getNextNode().getNextNode().getNextNode() can become header.nextNode.nextNode.element and so forth.
Stage 2
Now that that's out of the way, we have the question of how useful this type of structure will actually be for your application. My biggest concern in looking at this is the fact that, when applying edges between nodes on your graph, you will need to access arbitrarily indexed Nodes to attach edges to them... and while every Node already knows what its element index is, getting the Nth node takes N steps because your entire set of nodes is in a linked list.
Remember, the main advantage of using a linked list is the ability to remove arbitrary elements in O(1) time as you step through the list. If you are only building a list and aren't going to ever remove anything from it, arrays are often faster -- especially if you ever need to access arbitrary elements.
What if you don't need to guarantee they're in any particular order or access them by their index, but you need to be able to add, access-by-ID, and remove them very quickly for larger data sets? HashSet may be the thing for you! What if you still need to be able to access them all in the order they were added? LinkedHashSet is your best friend. With this, you could easily even give the nodes names that are strings with no real slowdown.
As for the edges, I feel you are already doing fine: it's probably best to implement the outgoing edges for each Node in a singly linked list, assuming you will rarely be removing edges or will have a small number of edges per node and will always access them all together. To add a new edge, simply say newEdge = new Edge(); newEdge.nextEdge = firstEdge; firstEdge = newEdge; and you're done, having added the new edge to the beginning of the list. (Singly linked lists are easiest to use as stacks rather than queues.)
For extra fancy-points, implement Iterable<Edge> with your Node class and make a little Iterator class so you can use extended-for to visit every edge and make your life even easier!
As #Widdershins says, the terms used makes the algorithm hard to understand.
I would recommend two things in order to refactor your code:
Review the terminology (maybe this helps: http://en.wikipedia.org/wiki/Glossary_of_graph_theory). I know that it sounds like a silly recommendation, but using proper terms will help you a lot to review the object model.
Use a better representation. In your code a Node fills multiple roles, which makes the code hard to follow.
A good representation will depend a lot of the kind of problems that you try to resolve. For example an Adjacency List, or a Matrix are useful to apply some algorithms of graph theory.
But if you only want to exercise with an object oriented design, is useful to start with the basics.
Take the definition of a Graph in mathematics: G = (V, E)... a graph is a pair of a set of nodes and a set of edges between those nodes, and translate it to code:
(the example uses fields for brevity)
class DirectedGraph {
final Set<Node> nodes = new HashSet<Node>();
final Set<Edge> edges = new HashSet<Edge>();
}
Now you need to extend this definition. You can do it step by step. I did the same to end with this representation:
class DirectedGraph {
final Set<Node> nodes = new HashSet<Node>();
final Set<Edge> edges = new HashSet<Edge>();
public Node addNode(Object value) {
Node newNode = new Node(value);
nodes.add(newNode);
return newNode;
}
public Edge addEdge(Node src, Node dst) {
Edge newEdge = new Edge(src, dst);
edges.add(newEdge);
return newEdge;
}
private assertValidNode(Node n) {
if (n.graph != this)
throw new IllegalArgumentException("Node " + n + " not part of the graph");
}
public Set<Node> successorsOf(Node n) {
assertValidNode(n);
Set<Node> result = new HashSet<Node>();
for (Edge e : edges) {
if (e.src == n) { result.add(e.dst); }
}
return result;
}
class Node {
final graph = DirectedGraph.this;
final Object value;
Node(Object v) {
this.value = v;
}
public String toString() { return value.toString(); }
public Set<Node> successors() {
return graph.successorsOf(this);
}
// useful shortcut
public Node connectTo(Node... nodes) {
for (Node dst : nodes) {
graph.addEdge(this, dst);
}
return this;
}
}
class Edge {
final graph = DirectedGraph.this;
final Node src; final Node dst;
Edge(Node src, Node dst) {
graph.assertValidNode(src);
graph.assertValidNode(dst);
this.src = src; this.dst = dst;
}
public String toString() { return src.toString() + " -> " + dst.toString(); }
}
}
DirectedGraph g = new DirectedGraph();
DirectedGraph.Node one = g.addNode(1);
DirectedGraph.Node two = g.addNode(2);
DirectedGraph.Node three = g.addNode(3);
DirectedGraph.Node four = g.addNode(4);
one.connectTo(two, three)
two.connectTo(four);
System.out.println(g.edges);
System.out.println(one.successors());
System.out.println(two.successors());
This strategy of representing the domain model in a "1 to 1" mapping, always helped me to "discover" the object model. Then you can improve the implementation for your specific needs (i.e. the running time of successorsOf can be improved by using an adjacency list).
Note that in this representation a Node and an Edge can only exist as a part of a graph. This restriction is not deduced directly from the math representation... but helps to maintain the constraints of a proper graph.
Note You can extract the inner-classes by constructing the Node and Edge with a parent graph reference.

Sorted linked list implementation

i am a novice programmer, to be specific, i am learning java programming and i am supposed to implement sortedLinkedList class that extends LinkedList class from the java library. The list has to store persons in ascending order of their surnames. I have already written my Person class that implements Comparable interface. my problem is, I have been struggling implementing this sortedLinkedClass but to no avail. My code runs without any compiling or run time error but the program does not print anything. Another thing as you can see , I am testing it with Integers instead of Persons and it throws NullPointerException when trying to add a number that is already in the list. My code is as it is below.
import java.util.*;
public class SortedLinkedList< E> extends LinkedList<E>
{
private Link<E> first;
private Link<E> last;
/**
* Constructor for objects of class SortedLinkedList
*/
public SortedLinkedList()
{
//super();
first = null;
last = null;
}
/*
* Link class for creating Link nodes in the SortedLinkedList objects
*/
private class Link<E>
{
public Comparable<E> data;
public Link next;
}
/*
* Overiding add method from LinkedList class
*/
public boolean add(E obj)
{
Link newLink = new Link();
newLink.data = (Comparable<E>)obj;
// When the list is initially empty
if (first == null)
{
first = newLink;
last = newLink;
return true;
}
// When the element to be added is less than the first element in the list
if (newLink.data.compareTo(first.data) < 0)
{
//newLink.data = obj;
newLink.next = first;
first = newLink;
return true;
}
// When the element to be added is greater than every element in in list
// and has to be added at end of the list
if (newLink.data.compareTo(last.data) > 0)
{
//newLink.data = obj;
last.next = newLink;
last = newLink;
return true;
}
//When the element to be added lies between other elements in the list
if (newLink.data.compareTo(first.data) >= 0 && newLink.data.compareTo(last.data) <= 0)
{
//newLink.data = obj;
Link current = first.next;
Link previous = first;
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
previous.next = newLink;
newLink.next = current;
}
return true;
}
public static void main (String[] args)
{
LinkedList<Integer> list = new SortedLinkedList<Integer>();
list.add(4);
list.add(5);
list.add(10);
list.add(9);
//list.add(5);
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext())
{
System.out.println(iterator.next());
}
}
}
If you must use a LinkedList, all you really have to do is override the "add" method so that it inserts your element in the correct position. You can do that by invoking the add(integer,Object) method which inserts your element in a specific position.
Here's a quick and dirty (and non-generic :P) implementation of what I'm talking about.
public class PersonLinkedList extends LinkedList<Person> {
public boolean add(Person personToAdd) {
int index = 0;
for( ; index<size() ; index++){
Person personAlreadyInList = get(index);
if(personToAdd.compareTo(personAlreadyInList) < 0){
break;
}
}
add(index, personToAdd);
return true;
};
public static void main(String[] args) {
Person amy = new Person("Amy");
Person bob = new Person("Bob");
Person claire = new Person("Claire");
PersonLinkedList list = new PersonLinkedList();
list.add(bob);
list.add(claire);
list.add(claire);
list.add(amy);
list.add(bob);
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Person person = (Person) iterator.next();
System.out.println(person);
}
}
}
class Person implements Comparable<Person>{
private String name;
public Person(String name) { this.name = name; }
public String getName() { return name; }
#Override
public String toString() { return getName();}
#Override
public int compareTo(Person p) {
return name.compareTo(p.name);
}
}
The reason nothing gets printed is because you store the data in your own linked list data tree and not the LinkedList's data tree. You don't override the iterator method, so the iterator will loop through LinkedList's data which is empty. This is also a problem with all the other methods in LinkedList.
Are you sure you need to inherit from the LinkedList class or are you suppose to make your own class.
If you are supposed to inherit from LinkedList get rid of you node and use LinkedList for storing the data. Your add method would then use a ListIterator to find the correct spot for adding and use the add method of ListIterator.
If you don't inherit from LinkedList then extend AbstractSequentialList.
Note:
Both of these options should not be used in real code. Adding automatic sorting breaks the List interface.
The whole problem is a perfect example of "prefer composition over inheritance".
If this is homework do it as instructed, otherwise I'd recommend changing the exercise to implement a SortedCollection backed by a LinkedList. Then implement Collection and use a List as a member variable.
You could use a SortedSet if you don't need to support elements with the same sort key.
Also, the reason your code doesn't print anything is because you override adding items to the list, but not iterating (the iterator() or listIterator() methods.) Extending LinkedList doesn't automagically make your data structure iterable unless you modify its contents using the base class add(), remove(), and other methods.
besides iterator, add/remove override, I think your algorithm to sort is not correct. And that leads to the nullpointer exception when you add existing elements into your "sortedLinkedList".
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
I think what you wanted is while (newLink.data.compareTo(current.data) >0) . not <=0. here is the mistake.
since "=0" is in while condition, it will go through the whole list, till the last element, then execute:
(current is the last now)
previous = current;
current = current.next; (now, current is Null, since last.next is Null)
finally, current is Null, then comes again, current = current.next; Bang! Nullpointer.
so I guess the Nullpointer was thrown at this line.

Categories