Problem Definition
I need a collection which has nodes and each node has a constant size partially filled array. Each array may contain different size as long as smaller than previously defined constant size. There will be list of these nodes.
For example :
When an element is needed to be added to the list , list adds an element at the first appropriate node which is not full. If i continuously add(1) , add(2) , add(3) , add(4) , add(1) , list will be demonstrated like this :
Suppose DEFAULT_NODE_CAPACITY = 3
node-0 -> "123"
node-1 -> "41"
When an element is needed to be removed from the list , list removes an element from the first appropriate node which contains and matched with given element. If i remove(1) from the list , list will be demonstrated like this :
node-0 -> "23"
node-1 -> "41"
What did I try ?
I have considered the using inner class which is static one , because node class should not access the fields and methods of outher class. All types must have been generic so I put the generic key value that is identical for each constructor.
Critical point was that I had to use AbstractList class in my custom collection.At this point I really confuse about what structure that i will be use for invocating node class which has partially fixed array.
Questions
How can I override AbstractList methods which conform my node inner class . When I read the Java API Documentation , for creating modifiable i just need to override
get()
set()
remove()
add()
size()
at this point , how can i override all of them efficiently by conforming my problem definition ?
What data type should I use for invocating Node<E> ? and How can implement it ?
How did I implement ?
package edu.gtu.util;
import java.util.AbstractList;
import java.util.Collection;
import java.util.List;
public class LinkedArrayList<E> extends AbstractList<E>
implements List<E> , Collection<E>, Iterable<E> {
public static final int DEFAULT_CAPACITY = 10;
public static final int CONSTANT_NODE_CAPACITY = 3;
/* Is that wrong ? , how to be conformed to AbstractList ? */
private Node<E>[] listOfNode = null;
/*---------------------------------------------------------*/
private int size;
private static class Node<E> {
private Object[] data;
private Node<E> next = null;
private Node<E> previous = null;
private Node( Object[] data , Node<E> next , Node<E> previous ) {
setData(data);
setNext(next);
setPrevious(previous);
}
private Node( Object[] data ) {
this( data , null , null );
}
private void setData( Object[] data ) {
this.data = data;
}
private void setNext( Node<E> next ) {
this.next = next;
}
private void setPrevious( Node<E> previous ) {
this.previous = previous;
}
private Object[] getData() {
return data;
}
private Node<E> getNext() {
return next;
}
private Node<E> getPrevious() {
return previous;
}
}
private void setSize( int size ) {
this.size = size;
}
public LinkedArrayList() {
super();
}
public LinkedArrayList( int size ) {
super();
setSize( size );
listOfNode = (Node<E>[]) new Object[size()];
}
public LinkedArrayList(Collection<E> collection ) {
super();
}
#Override
public E get( int i ) {
}
#Override
public boolean add(E e) {
return super.add(e);
}
#Override
public boolean remove(Object o) {
return super.remove(o);
}
#Override
public E set(int index, E element) {
return super.set(index, element);
}
#Override
public int size() {
return size;
}
}
First, you need to add a field to Node that tells you how many data items are stored in that node.
Then:
size has to iterate over the nodes and compute the sum of the sizes of the nodes. Or you can maintain a separate size, and update it with every add and remove.
add has to find the node where the item can be inserted. If there's room in that node, just add it there. If that node is full, you have to create a new node.
remove has to find the right node and remove the item from that node. If the node becomes empty, the node itself can be removed.
get has to iterate over the nodes, keeping track of how many items it skips over, until it find the node that must contain the node.
set - same as get, except that it replaces the item in addition to returning it
You'll find better descriptions in wikipedia: https://en.wikipedia.org/wiki/Unrolled_linked_list
This article also suggests an important optimization for add/remove.
I was trying to delete the first node of Linked List using Node head but it did not work while it works when I used list.head?
import java.util.*;
// Java program to implement
// a Singly Linked List
public class LinkedList {
Node head;
// head of list
// Linked list Node.
// This inner class is made static
// so that main() can access it
static class Node {
int data;
Node next;
// Constructor
Node(int d)
{
data = d;
next = null;
}
}
static void delete(LinkedList list,int x){
Node curr=list.head,prev=list.head;
if(curr.data==x&&curr!=null){
list.head=curr.next;
return ;
}
while(curr.data!=x&&curr.next!=null){
prev=curr;
curr=curr.next;
}
if(curr.data==x)
prev.next=curr.next;
return ;
}
// There is method 'insert' to insert a new node
// Driver code
public static void main(String[] args)
{
/* Start with the empty list. */
LinkedList list = new LinkedList();
list = insert(list, 1);
list = insert(list, 2);
list = insert(list, 3);
list = insert(list, 4);
delete(list,1);
printList(list);
//There is method to print list
}
}
//Output : 2 3 4
When I use code above I am able to delete the first node but when I use this code it does not work
import java.util.*;
// Java program to implement
// a Singly Linked List
public class LinkedList {
Node head;
// head of list
// Linked list Node.
// This inner class is made static
// so that main() can access it
static class Node {
int data;
Node next;
// Constructor
Node(int d)
{
data = d;
next = null;
}
}
static void delete(Node head,int x){
Node curr=head,prev=head;
if(curr.data==x&&curr!=null){
head=curr.next;
return ;
}
while(curr.data!=x&&curr.next!=null){
prev=curr;
curr=curr.next;
}
if(curr.data==x)
prev.next=curr.next;
return ;
}
// There is method 'insert' to insert a new node
// Driver code
public static void main(String[] args)
{
/* Start with the empty list. */
LinkedList list = new LinkedList();
list = insert(list, 1);
list = insert(list, 2);
list = insert(list, 3);
list = insert(list, 4);
delete(list.head,1);
printList(list);
//There is method to print list
}
}
//Output: 1 2 3 4
I was wondering that these are the same thing are different, Node head and list(LinkedList).head
Note: Both method work for other nodes, the difference is only for the first node.
In first one you are passing your list as input and in second one reference to your head node and if you will notice in first example you are modifying your list's head if data is present at first node.Here's the code snippet which is doing this.
Node curr=list.head,prev=list.head;
if(curr.data==x&&curr!=null){
list.head=curr.next;
return ;
}
But in your second example if data is found at first node then your are assigning curr.next to head variable which is local to the method so lists's head value remain unchanged and when you try to print list in main method again it shows old head. Here's the code snippet from second example
Node curr=head,prev=head;
if(curr.data==x&&curr!=null){
head=curr.next;
return ;
}
So if you are storing your head pointer in LinkedList object then you must modify your value in it.
class linkedqueue <item_t> {
private class node{
item_t item;
node link;
public node(item_t t, node l){
item=t;
link=l;
}
private node front = null;
private node rear = null;
public void insert (item_t any) {
this.link=new node(any,this.link);
}
the insert method should add "any" to the end of the queue. It works only in the node class, but now it is in the linkedqueue class, I don't know how to fix the "this.link" part..
The last node in the LinkedList will point to a null value. So, grab the last Node in the list, set its next node to the new node you are passing in, and lastly set the new node's next pointer to null, indicating the end of the list.
private void addLast(Node<T> aNode)
{
Node<T> head, lastNode;
head = this.getHead();
mySize++;
if(head == null)
{
this.addFirst(aNode);
}
else
{
lastNode = this.getPrevious(null); // get last Node, which is the Node previous to Null
lastNode.setNext(aNode); // add the new node to the end of the list
aNode.setNext(null); //set the new node's next pointer to null, indicating the end of the list
}
}
Im trying to write the methods to "union" which can be described: if A, B, C are sets, has the form C = A.union(B). Union returns a Set that contains all the elements in set A and B, but only list duplicates once.
My idea for this method is to traverse set A and add all of its elements to the union set, then traverse set B, if an element of set B is already present in the union set, then do not insert it to result, otherwise insert all to the union set.
This is complicated for a beginner like me since I want to include all 3 lists into the method (which I get a bunch of errors). I already wrote some methods in my SLinkedList class to check and add element but the parameters take an object from a Node
/** Singly linked list .*/
public class SLinkedList {
protected Node head; // head node of the list
protected int size; // number of nodes in the list
/** Default constructor that creates an empty list */
public SLinkedList() {
head = new Node(null, null); // create a dummy head
size = 0;
// add last
public void addLast(Object data) {
Node cur = head;
// find last node
while (cur.getNext() != null) {
cur = cur.getNext();
}
// cur refers to the last node
cur.setNext(new Node(data, null));
size++;
}
// contain method to check existing elements
public boolean contain (Object target) {
boolean status = false;
Node cursor;
for (cursor = head; cursor != null; cursor = cursor.getNext()) {
if (target.equals(cursor.getElement())) {
status = true;
}
}
return status;
}
public SLinkedList union (SLinkedList secondSet) {
SLinkedList unionSet = new SLinkedList();
secondSet = new SLinkedList();
Node cursor;
for(cursor = head.getNext(); cursor != null; cursor = cursor.getNext()) {
unionSet.addLast(cursor.getElement());
// traverse secondSet, if an element is existed in either set A or union
// set, skip, else add to union set
}
}
return unionSet;
}
}
Node class
/** Node of a singly linked list of strings. */
public class Node {
private Object element; // we assume elements are character strings
private Node next;
/** Creates a node with the given element and next node. */
public Node(Object o, Node n) {
element = o;
next = n;
}
/** Returns the element of this node. */
public Object getElement() { return element; }
/** Returns the next node of this node. */
public Node getNext() { return next; }
// Modifier methods:
/** Sets the element of this node. */
public void setElement(Object newElem) { element = newElem; }
/** Sets the next node of this node. */
public void setNext(Node newNext) { next = newNext; }
}
*update*
The question is if there is a second list involved public SLinkedList union (SLinkedList secondSet) , what syntax should i use to traverse set B and check if an element of set B is already present in result then do not insert it to result, otherwise insert. Do I need to creat a node for set B and traverse it?, there may be a compare method to compare the 2 sets outside of the union method?
Please help. Thanks all.
SLinkedList unionSet = null; // need a new SLinkedList() here
Node cursor;
for(cursor = head.getNext(); cursor != null; cursor = cursor.getNext()) {
unionSet.addLast(cursor.getElement()); // NPE because unionSet is null
}
I thought I had understanding of this in my previous question about linked lists, but I was terribly mistaken, I'm just as lost as I was when I initially posted.
I realize that I'm technically asking two questions, but hopefully getting at least one should make the other easy (assuming they are just reverse of each other).
I have 3 classes already given to me, they are:
SLinkedList.java
package chapter3.linkedList;
public class SLinkedList<V> {
// instance variables. Add the tail reference.
protected Node<V> head, tail;
protected long size;
// methods, empty list constructor first
public SLinkedList () {
head = null;
tail = null;
size = 0;
} // end constructor of a SLinkedList
// method to add nodes to the list. Storage space for the node
// is already allocated in the calling method
public void addFirst (Node<V> node) {
// set the tail only if this is the very first node
if (tail == null)
tail = node;
node.setNext (head); // make next of the new node refer to the head
head = node; // give head a new value
// change our size
size++;
} // end method addFirst
// addAfter - add new node after current node, checking to see if we are at the tail
public void addAfter (Node<V>currentNode, Node<V>newNode) {
if (currentNode == tail)
tail = newNode;
newNode.setNext (currentNode.getNext ());
currentNode.setNext (newNode);
// change our size
size++;
} // end method addAfter
// addLast - add new node after the tail node. Adapted from Code Fragment 3.15, p. 118.
// Mike Qualls
public void addLast (Node<V> node) {
node.setNext (null);
tail.setNext (node);
tail = node;
size++;
} // end method addLast
// methods to remove nodes from the list. (Unfortunately, with a single linked list
// there is no way to remove last. Need a previous reference to do that. (See
// Double Linked Lists and the code below.)
public Node<V> removeFirst () {
if (head == null)
System.err.println("Error: Attempt to remove from an empty list");
// save the one to return
Node<V> temp = head;
// do reference manipulation
head = head.getNext ();
temp.setNext(null);
size--;
return temp;
} // end method removeFirst
// remove the node at the end of the list. tail refers to this node, but
// since the list is single linked, there is no way to refer to the node
// before the tail node. Need to traverse the list.
public Node<V> removeLast () {
// // declare local variables/objects
Node<V> nodeBefore;
Node<V> nodeToRemove;
// make sure we have something to remove
if (size == 0)
System.err.println("Error: Attempt to remove fron an empty list");
// traverse through the list, getting a reference to the node before
// the trailer. Since there is no previous reference.
nodeBefore = getFirst ();
// potential error ?? See an analysis and drawing that indicates the number of iterations
// 9/21/10. size - 2 to account for the head and tail nodes. We want to refer to the one before the
// tail.
for (int count = 0; count < size - 2; count++)
nodeBefore = nodeBefore.getNext ();
// save the last node
nodeToRemove = tail;
// now, do the pointer manipulation
nodeBefore.setNext (null);
tail = nodeBefore;
size--;
return nodeToRemove;
} // end method removeLast
// method remove. Remove a known node from the list. No need to search or return a value. This method
// makes use of a 'before' reference in order to allow list manipulation.
public void remove (Node<V> nodeToRemove) {
// declare local variables/references
Node<V> nodeBefore, currentNode;
// make sure we have something to remove
if (size == 0)
System.err.println("Error: Attempt to remove fron an empty list");
// starting at the beginning check for removal
currentNode = getFirst ();
if (currentNode == nodeToRemove)
removeFirst ();
currentNode = getLast ();
if (currentNode == nodeToRemove)
removeLast ();
// we've already check two nodes, check the rest
if (size - 2 > 0) {
nodeBefore = getFirst ();
currentNode = getFirst ().getNext ();
for (int count = 0; count < size - 2; count++) {
if (currentNode == nodeToRemove) {
// remove current node
nodeBefore.setNext (currentNode.getNext ());
size--;
break;
} // end if node found
// change references
nodeBefore = currentNode;
currentNode = currentNode.getNext ();
} // end loop to process elements
} // end if size - 2 > 0
} // end method remove
// the gets to return the head and/or tail nodes and size of the list
public Node<V> getFirst () { return head; }
public Node<V> getLast () { return tail; }
public long getSize () { return size; }
} // end class SLinkedList
There's also Node.java
package chapter3.linkedList;
public class Node<V>
{
// instance variables
private V element;
private Node<V> next;
// methods, constructor first
public Node ()
{
this (null, null); // call the constructor with two args
} // end no argument constructor
public Node (V element, Node<V> next)
{
this.element = element;
this.next = next;
} // end constructor with arguments
// set/get methods
public V getElement ()
{
return element;
}
public Node<V> getNext ()
{
return next;
}
public void setElement (V element)
{
this.element = element;
}
public void setNext (Node<V> next)
{
this.next = next;
}
} // end class Node
and finally GameEntry.java
package Project_1;
public class GameEntry
{
protected String name; // name of the person earning this score
protected int score; // the score value
/** Constructor to create a game entry */
public GameEntry(String name, int score)
{
this.name = name;
this.score = score;
}
/** Retrieves the name field */
public String getName()
{
return name;
}
/** Retrieves the score field */
public int getScore()
{
return score;
}
/** Returns a string representation of this entry */
public String toString()
{
return name + ", " + score + "\n";
}
}
EDIT POINT
I created a driver called Scores.java, in it so far all I have is **I have added what I THINK i need for the classes, I'm probably wrong though:
package Project_1;
import chapter3.linkedList.*;
import java.util.*;
/** Class for storing high scores in an array in non-decreasing order. */
public class Scores
{
//add function
public SLinkedList<GameEntry> add(GameEntry rank, SLinkedList<GameEntry> scores)
{
Node<GameEntry> currentNode = scores.getFirst();
Node<GameEntry> nextNode = null;
Node<GameEntry> previousNode = null;
Node<GameEntry> newNode = new Node<GameEntry>();
newNode.setElement(rank);
if(scores.getSize() == 0)
{
scores.addFirst(newNode);
}
else
{
while(currentNode != null)
{
nextNode = currentNode.getNext();
if(nextNode == null)
{
scores.addLast(newNode);
}
else
{
scores.addAfter(currentNode, newNode);
break;
}
previousNode = currentNode;
currentNode = currentNode.getNext();
}
}
return scores;
}
//remove function
public void remove(int i)
{
}
//print function
/*gameenter printing;
printing=node.Getelement; //pseudo code for making it work right
print(printing.getscore)
print(print.getname)
*/
public void print(SLinkedList<GameEntry> scores)
{
Node<GameEntry> currentNode = scores.getFirst();
GameEntry currentEntry = currentNode.getElement();
System.out.printf("[");
for(int i = 0; i < scores.getSize(); i++)
{
System.out.printf(", %s", currentEntry.toString());
currentNode = currentNode.getNext();
currentEntry = currentNode.getElement();
}
System.out.println("]");
}
}
I have my test driver called ScoresTest.java, that I have pretty much filled out:
package Project_1;
import chapter3.linkedList.SLinkedList;
public class ScoresTest {
/**
* #param args
*/
public static void main(String[] args)
{
SLinkedList<GameEntry> highScores = new SLinkedList<GameEntry>(); //Linked List for Game Entry
GameEntry entry;
Scores rank = new Scores();
entry = new GameEntry("Flanders", 681);
highScores = rank.add(entry, highScores);
entry = new GameEntry("Krusty", 324);
highScores = rank.add(entry, highScores);
entry = new GameEntry("Otto", 438);
highScores = rank.add(entry, highScores);
entry = new GameEntry("Bart", 875);
highScores = rank.add(entry, highScores);
entry = new GameEntry("Homer", 12);
highScores = rank.add(entry, highScores);
entry = new GameEntry("Lisa", 506);
highScores = rank.add(entry, highScores);
entry = new GameEntry("Maggie", 980);
highScores = rank.add(entry, highScores);
entry = new GameEntry("Apoo", 648);
highScores = rank.add(entry, highScores);
entry = new GameEntry("Smithers", 150);
highScores = rank.add(entry, highScores);
entry = new GameEntry("Burns", 152);
highScores = rank.add(entry, highScores);
System.out.println("The Original High Scores");
rank.print(highScores);
entry = new GameEntry("Moe", 895);
highScores = rank.add(entry, highScores);
System.out.println("Scores after adding Moe");
rank.print(highScores);
//highScores = rank.remove(4);
System.out.println("Scores after removing Apoo");
rank.print(highScores);
}
}
That's entirely finished, pretty sure I have nothing left to add for it.
I'm not looking for someone to answer it for me, but I have no clue where to start or how to make the add or remove function, in any way. This is an intermediate course, the book does nothing for explaining linked lists (go ahead and look for yourself if you don't believe me, text is called Datastructures and Algorithms in Java, 5th edition). It shows how to do such with an array quite easily...which works perfectly for a linked list, but apparently the teacher does not want us doing it this way, so sadly I am now utterly lost on how to do this.
I've tried looking at other peoples answers on here, and google, and so far nothing has clicked or made any sense at all, I just can't grasp how it works, and the teacher's explanation and example was only to draw boxes on the board, I've never seen a sort, add, or remove function coded for a linked list...can't know what I've not been taught or can't locate.
Any help is greatly appreciated, and thank you in advance!
EDIT
I looked at the import java.util.*; and the commands within it for linked lists, they seem painfully easy. to remove I'd just use list.sublist(i, i).clear(); and the value I wish to remove is removed, super easy, it seems to be just trying to utilize the slinkedlist.java and node.java, I just can't seem to follow them in any way shape or form. I believe the teacher did indeed write them, and I've tried asking for his assistance, stayed 2 hours after class trying to get any understanding from him, and as you can see it did not help much at all. Thank you again for the assistance!
EDIT
I also apologize if this seems like it is vague, but I don't have a specific point where my confusion seems linked, I understand linked lists if we're talking about the java.util.linkedList;, but as far as using what I've been given in this circumstance, I can't follow the logic at all, leaving me quite lost and unsure of where to begin.
In pseudo-code (please note I am not including bound checking etc, simply the logic)
To add a node to the front of the list:
newNode->nextNode = startNode
startNode = newNode
To add to a specific index:
index = 0
currentNode = startNode
// find the node in the list. here you will need to do all kinds of bound checking
while index is less than position
currentNode = currentNode.nextNode // move your node pointer to the position
increment index
// so here we basically insert the new node into the list. what needs to happen is
// to NOT break the list by forgetting the node after the current node. this is why
// we first set the new nodes' next one, to the current nodes' (the one already in
// the list) next node. this way, we still have all the information we need. then,
// when we set the current nodes' next node to the new node, we essentially "break"
// the link and "repair" it by adding the new link.
newNode.nextNode = currentNode.nextNode // some more bound checking required
currentNode.nextNode = newNode
To remove from a specific index:
index = 0
delNode = startNode
// find the node in the list. here you will need to do all kinds of bound checking
while index is less than (position - 1)
delNode = delNode.nextNode // move your node pointer to the position
increment index
delNode.nextNode = delNode.nextNode.nextNode
// that's it. by setting the node's (before the one you whish to delete)
// next node to the node AFTER the one you want to delete, you basically
// "skip" over that node. since it is no longer referenced, the garbage
// collector will take care of the rest. if you wish to return that node
// you can do it quite easily by remembering it.
storeNode = delNode.nextNode // some more bound checking required
delNode.nextNode = delNode.nextNode.nextNode // some more bound checking required
// now you still have a reference to the deleted node in storeNode
UPDATE
OK, so if I understand correctly, you need to create a linked list that stores scores in a ascending order. As far as I can see, the entire linked list has been implemented for you, you simply need to use the classes provided, and add the logic in Scores.java to keep the list sorted.
First off, I see your nodes are not comparable. If you are at all allowed to change the source given to you, I would suggest having them implement Comparable<Node> and also override the equals(Object o) so that you have logic to compare them. Two nodes can contain the same element, but that does not mean that they are equal.
Please note the change in the method signatures!
//add function
public void add(Node<GameEntry> score) {
// adding is where you now want to keep everything sorted. so I highly
// recommend that you implement `Comparable` as I mentioned above. if not,
// you have to put the logic in here.
Node<GameEntry> currentNode = highScored.getFirst();
Node<GameEntry> prevNode = null;
// if the list is empty, or the new node must go in before the head,
// simply add it as the head.
if (highScores.size() == 0 || score.compareTo(currentNode) < 0) {
highScores.addFirst(score);
}
// search for the position of the new node. while the node has a higher score
// than the current node, we need to continue on so we can place it in the
// correct place.
while (currentNode != null && currentNode.compareTo(score) > 0) {
prevNode = currentNode;
currentNode = currentNode.getNext();
}
// if the currentNode is null, it means it is the highest score, so
// we can simply add it to the end
if (currentNode == null) {
highScores.addLast(score);
} else {
// otherwise just add it after the correct node
highScores.addAfter(prevNode, score);
}
}
//remove function
public void remove(Node<GameEntry> score) {
// removing an element should be as described above. if you keep
// your list sorted during the ADD method, removing any element
// should not break the order.
// find the element - removal from a linked list is O(n),
// since we need to know what the element BEFORE the one
// is that you want to remove. assuming you have implemented
// the equals method to check equality of nodes:
Node<GameEntry> currentNode = highScores.getFirst();
Node<GameEntry> prevNode = null;
while (currentNode != null && !currentNode.equals(score)) {
prevNode = currentNode;
currentNode = currentNode.getNext();
}
// if currentNode is null, the node we wanted to remove was not
// in the list.
if (currentNode == null) {
System.out.println("Node not found");
return;
}
// now, we need to check if there is a node after the one we want
// to remove.
if (prevNode.getNext().getNext() != null) {
// if there is, we follow the logic from the pseudo code
prevNode.setNext(prev.getNext().getNext());
} else {
// if not, we only need to remove the last entry (since the
// one we want to remove is the last one)
highScores.removeLast();
}
}
IMPORTANT
Please just double check the logic here. I did it really quickly without an IDE as I'm not at my development computer at the moment. If anyone finds any issues, please leave a comment and I'll fix it.
If this is not exactly what you asked (your question is a bit vague), let me know.
UPDATE 2
Read up on Comparators here, here and here.