Java : singly linked list, dummy node, insert - java

public class A<E> extend AbstractList<E>{
private SLNode<E> Head = new SLNode<E>
private int length = 0; // length of the list
// I will skip the class of SLNode<E>
// Head's element and successor is initialized as null in the class SLNode<E>
public void add(int index, E element) // insert an element in the list
{
// if index is less than 0 or greater than the length
if( (index < 0) || (index > length ) )
throw new IndexOutOfBoundsException();
if(index ==0)
{
SLNode<E> newnode = new SLNode<E>(element, null); // make new node
newnode.setSuccessor(Head.getSuccessor());
Head.setSuccessor( newnode);
length++;
}
}
Q1. Is this right way of adding element at the front of the list? (using dummy header node, but no tail)
Q2. Would it be the same whether the list is empty or non-empty?

That's not a bad way to do it, though using a "dummy" node for "head" is somewhat unusual.
But it has the advantage that you can replace "Head" with "current", initialize that to "Head", then "crawl" up the list index nodes and do your insert, and you wouldn't have to special-case the zero case.
public void add(int index, E element) // insert an element in the list
{
// if index is less than 0 or greater than the length
if( (index < 0) || (index > length ) ) {
throw new IndexOutOfBoundsException();
}
// Find insertion point
SLNode<E> current = Head;
for (int i = 0; i < index; i++) {
current = current.getSuccessor();
}
// Create & insert new node
SLNode<E> newnode = new SLNode<E>(element, null);
newnode.setSuccessor(current.getSuccessor());
current.setSuccessor( newnode);
length++;
}
(But note that standard naming convention is to reserve names with initial upper-case for class names.)

Assuming that this is your insert at head method, I dont understand why you need to pass index in. Ideally I would like to have just 1 method for insert. But since you are specfically asking for insert at head.
public void addToHead(E element) // insert an element at head
{
if(length==0)
throw new Exception("head does not exist");
element.setSuccessor(head);
head = element;
length++;
}

I don't think you really need to have a special case for inserting at the front of the list. Inserting at the front of this list is no different from inserting anywhere else in the list.
public void add(int index, E element)
{
// if index is less than 0 or greater than the length
if ((index < 0) || (index > length))
throw new IndexOutOfBoundsException();
SLNode<E> previousNode = head;
for ( int i = 0; i < index; i++ ) {
previousNode = previousNode.getSuccessor();
}
SLNode<E> newNode = new SLNode<E>(element, previousNode.getSuccessor());
previousNode.setSuccessor(newNode);
length++;
}
Basically, this just traverses the list to find the correct node to insert after - if the index is 0, it immediately stops at head. Once you have the node to insert after, you perform these three steps:
Create a new node and set its successor to the successor of the previous node
Set the successor of the previous node to be the new node
Add one to the length of the list
I ran a couple little tests on this and it seemed to work just fine.
Note that this approach pretty much assumes that head will never actually be considered an element in the list. It's really just a place to start the list. By that, I mean that head.getElement() will always return null - it's not really part of the list. I'm not sure if that's the implementation you wanted, but it seemed to make the most sense when you said that you start the list with a head element, even when the list is supposed to be empty.

Q1. Is this right way of adding element at the front of the list?
(using dummy header node, but no tail)
EDIT: After rereading your question, and trying your code, I would say yes.
Q2. Would it be the same whether the list is empty or non-empty?
EDIT: Yes, it appears to work on an empty list.
dummy_header_list<String> theList = new dummy_header_list<String>();
System.out.println(theList);
theList.add(0,"first add");
System.out.println(theList);
theList.add(0,"second add");
System.out.println(theList);
theList.add(0,"third add");
System.out.println(theList);
gives:
[]
[first add]
[second add,first add]
[third add,second add,first add]
with this toString:
public String toString()
{
String output = "[";
SLNode<E> temp = Head.getSuccessor();
while ( temp != null ) {
if ( output.length() == 1 ) {
output = output + temp.toString();
}
else {
output = output + "," + temp.toString();
}
temp = temp.getSuccessor();
}
output = output + "]";
return output;
}

Related

Add method java

I want to add a method add(int index, E element) in Java, that inserts a specified element at a specified index in the list and shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices). But I guess something is wrong with the indices in my code in the for-loop. Any ideas how to solve it?
public class SingleLinkedList<E> implements ISingleLinkedList<E> {
Node head;
int size = 0;
#Override
public void add(int index, E element) throws IndexOutOfBoundsException {
Node newNode = new Node(element);
if(head == null && index == 0) {
head = newNode;
}
else if (index == 0 && head != null) {
Node tempNode = new Node(element);
tempNode.setmNextNode(head);
head = tempNode;
}
else {
Node tempNode = head;
for(int i = 1; i<index; i++) {
tempNode = tempNode.getmNextNode();
}
/**Node newNode = new Node(element);**/
newNode.setmNextNode(tempNode);
tempNode.setmNextNode(newNode);
}
size++;
}
}
My code for the Node class is:
public class Node<E> {
private E mElement;
private Node<E> mNextNode;
Node(E data) {
this.setmElement(data);
}
public E getmElement() {
return this.mElement;
}
public void setmElement(E element) {
this.mElement = element;
}
public Node<E> getmNextNode()
{
return this.mNextNode;
}
public void setmNextNode(Node<E> node)
{
this.mNextNode = node;
}
The problem is that I have a JUnit test that fails when adding this method and I do not know what more I need to add in order to pass the test.
#Test
public void testAddWithIndexesToListWith5Elements() {
int listSize = 5;
// First create an ArrayList with string elements that constitutes the test data
ArrayList<Object> arrayOfTestData = generateArrayOfTestData(listSize);
// Then create a single linked list consisting of the elements of the ArrayList
ISingleLinkedList<Object> sll = createSingleLinkedListOfTestData(arrayOfTestData);
// Add new elements first, in the middle and last to the ArrayList of test data
// and the single linked list
try {
arrayOfTestData.add(0, 42);
arrayOfTestData.add(3, "addedElement1");
arrayOfTestData.add(7, "addedElement2");
sll.add(0, 42);
sll.add(3, "addedElement1");
sll.add(7, "addedElement2");
}
catch (Exception e) {
fail("testAddWithIndexesToListWith5Elements - add() method failed");
}
// Check that the contents are equal
for (int i = 0; i < sll.size(); i++) {
assertEquals(arrayOfTestData.get(i), sll.get(i));
}
}
newNode.setmNextNode(tempNode);
tempNode.setmNextNode(newNode);
This is just going to create a cycle. It looks like your newNode should point to tempNode.getmNextNode() or something along those lines.
Your question is pretty unclear but I think I can see a problem.
If index is not 0, the you will iterate through the nodes until the index is reached.
If there are not enough elements in the list, you will reach the end of the list before the index where you want to insert the element.
In this case,
tempNode = tempNode.getmNextNode();
will set tempNode to null.
In the next iteration, this line will throw a NullPointerException.
You can bypass this issue by testing if tempNode.getmNextNode(); is null.
If that is the case, the element will just be inserted at the end/that point or will not be inserted.

POP method linked list

I've implemented a pop method in Java I would use it for delimiter matching, though it leaves one element in the list.
public int length(){
Node current = this.head;
int length = 0;
while(current != null){
current = current.getNextNode();
length += 1;
}
return length;
}
public char pop(){
Node current = this.head;
Node lastN = this.last;
for(int i = 0; i < length() - 2; i++){
current = current.getNextNode();
}
current.setNextNode(null);
this.last = current;
return lastN.getBracket();
}
How do I pop the first element if length is >= 1?, or any suggestion for improving my code.
Use java.util.LinkedList.
With addFirst(), addLast(), size(), removeFirst() and removeLast() you are covered.
Alternatively, check this delimiter check example for another way.
In you code, you miss the "initial" or "last element" case, which is special. You should check for the case of this.head == this.last; case where you should return the last element and clean up the list.
Why moving through the list elements in the loop? How about instead of that:
if (this.head != null)
{
char val = this.head.getBracket();
this.head = this.head.getNextNode();
}
This snippet will drop the first element and set head to point to the second element. I guess JVM will delete old head. If the list is circular, then also set last to point to the new head.

Removing all duplicates from a generic linked list

This is the code I've got so far, and it removes all the first instances of the duplicates but if I got an element repeated more than once it will only remove the first instance and leave the rest instances of this element in the list.
//remove all duplicate items from list.
// if list is null or empty leave it unchanged
public static <T extends Comparable<? super T>>
void deleteReps(LinkedList<T> list)
{
for (int i = 0; i < list.size(); i++)
{
T item = list.get(i);
for(int j = i + 1; j < list.size(); j++)
{
if(item == null && list.get(j) == item || item != null && item.equals(list.get(j)))
{
list.remove(j);
}
}
}
}
Following Eran's answer, I suggest you should iterate the list with Iterator since it eliminate the need for manual indexes and also allows for item removal while iterating the list.
When you remove an element from a list, you have to remember that this will reduce the index for every item after it in the list as well as the size of the list.
EDIT
As sharonbn suggested, here is a working method using an Iterator:
public static <T extends Comparable<? super T>> void deleteReps(LinkedList<T> list)
{
LinkedList<T> noRepsList = new LinkedList<T>();
Iterator<T> itr = list.iterator();
while(itr.hasNext())
{
T currentTest = itr.next();
if (!noRepsList.contains(currentTest))
noRepsList.add(currentTest);
else
itr.remove();
}
}
This may not be the most effective way to do this as it creates another list to compare objects with but it does get the job done.
With a LinkedList you are dealing with reference-based implementation of Objects that are linked together with Nodes. A Node contains an Object and a reference to the next Node only. You should try not to iterate through a LinkedList using indexes because when you start removing or adding Nodes, the indexes change. Unlike an Array that will keep a space null if you remove its content, once you remove a Node from a LinkedList, the list decreases in size, as the previous Node now references the Node that came after the one you deleted, and the deleted Node is lost in memory. So, in your example, you need to take into account that index will change after you remove a duplicate. For this reason, you should always try to traverse a LinkedList in Java via reference and not indexing. In your case, this might work:
void deleteReps(LinkedList<T> list)
{
Node prev = head; // A node to traverse with starts at the head
Node temp = head.getNext(); // A second node to traverse with
Node current = prev; // The node in question
while(prev.getNext() != null) // While the node after prev isn't the end
{ // of the list
T item = current.data; // The item we are looking for duplicates of
while(temp != null) // While temp isn't at the end of the list
{
if(temp.data == item) // If the item in temp is the same as the
{ // item we are looking for
prev.setNext(temp.getNext()); // Set the next Node of prev to the node
// after temp. This "deletes" the Node
// at temp
prev = temp; // prev is now temp
temp = temp.getNext(); // temp is the next Node
}
else // Else if the item is different
{
prev = temp; // prev is now temp
temp = temp.getNext(); // temp is now the next Node
}
} // end while
current = current.getNext(); // current is now the next Node
// so that the
// the next item we are looking for
// duplicates of is an item still in
// the LinkedList
prev = current;
temp = prev.getNext();
} // end while
}
I gave thorough comments so you could follow the logic behind this algorithm. This takes into account the shrinking LinkedList as you delete Nodes because current.getNext() will always be a Node that is still in the LinkedList after the deletion of duplicates occurs.

Why won't my linked list add nodes? (Java)

I'm trying to add a new Node to the end of my linked list but it doesn't seem to be doing anything. It adds the first element because it's a special case but then ignores all of the other assignments when I step through the debugging.
Here's the test I'm running:
#Test
public void testInsertElement()
{
PriorityList<String> list = new LinkedPriorityList<String>();
list.insertElementAt(0, "first");
list.insertElementAt(1, "second");
list.insertElementAt(2, "third");
assertEquals("first" , list.getElementAt(0));
assertEquals("second", list.getElementAt(1));
assertEquals("third" , list.getElementAt(2));
}
It fails on the second assertion because nothing is added after the first.
Here's the constructor for the Node Objects:
public class LinkedPriorityList<E> implements PriorityList<E> {
private class Node
{
private E data;
private Node next;
public Node(E element)
{
data = element;
next = null;
}
}
And finally the code that is failing on me:
public void insertElementAt(int index, E element) throws IllegalArgumentException
{
if(index>size() || index<0) //can only be between 0 and size()
throw new IllegalArgumentException();
if(size()==0)
first = new Node(element); //adding the first element. This works
else
{
if(index == size()) //if an element is being added to the end
{
Node ref = first; //assigning ref to the first element of the list
for(;ref!=null; ref = ref.next); //stepping through the list until ref is null
ref = new Node(element); //assigning the null reference a new Node. Doesn't assign
}
else //if an element is being inserted in the list. untested...
{
Node ref = first;
Node temp = new Node(element);
for(int i=1; i<index; i++)
ref = ref.next;
temp = ref.next;
ref = temp;
}
}
size++; //keeping track of how many elements in list
}
I think this works but if you want the get method too, here it is:
public E getElementAt(int index) throws IllegalArgumentException
{
if(index>=size() || index<0)
throw new IllegalArgumentException();
Node ref = first;
for(int i=0; i<index; i++)
ref = ref.next;
return ref.data;
}
When index == size, you want to create a new node, find the last node in the list, and assign the new node to its next pointer.
The last node is the one whose next pointer is null.
This should be enough to let you implement the algorithm by yourself.
This is probably what you meant to do:
for(; ref.next != null; ref = ref.next) {
/* intentionally empty */
}
ref.next = new Node(element);
Note that I'm both testing and assigning ref.next, not ref itself.
You need a temp node when adding at the end too (to keep track of the last element)
if (index == size())
{
Node ref = first, temp = first;
for (; ref != null; temp = ref, ref = ref.next);
temp.next = new Node(element);
}
By just assigning the new Node to ref; it doesn't link it to the current last node's next.

remove at index linked list

Hi im trying to remove a link in part of a linked list but i'm not sure how to remove the link. when i run it the links are still there. im using a junit to test the function if that matters .
Here is what i have so far.
public void removeAt(int k)
{
Node w = first;
int counter = 0;
if (k<0 || k >= size())
{
throw new IndexOutOfBoundsException("Error ");
}
else
{
while (w!= null)
{
counter++;
if (counter == k)
{
Node now = w.next;
w= now.next;
}
w=w.next;
}
}
assert check();
}
Thanks for the help
You need to change a node's .next field in order to remove a node, e.g. w.next = w.next.next removes the w.next node from the list (because nothing is pointing to it anymore); be sure to check for null pointers (if w.next is null then w.next.next will throw an exception). Also, add a break statement to the end of your if block since there's no need to traverse the rest of the list.
if (counter == k){
Node now = w.next;
w.next= now.next;
break;
}
test this.
You are updating a local variable. What you need to do is update the link prior to the current node:
if (k == 0)
{
first = first.next ;
// you also have to free the memory for first.
}
else
{
Node Last = first ;
w = first.next ;
counter = 1 ;
while (w!= null)
{
counter++; // Not sure your conventions, but I think this should be at the end
if (counter == k)
{
last.next = w.next ; /// happily skipping w :)
// remember you have to free w
break ; // no point in continuing to the end.
}
w=w.next;
}
}
}
You always need to keep track of the previous node. And also what if the node that's to be deleted is the first node? I guess you need to change the while block to look something like:
Node l = first;
while (w!= null)
{
if (counter == k)
{
if (w == first)
first = w.next;
else
l.next = w.next;
w.next = null;
break;
}
l=w;
w=w.next;
counter++;
}
Check the following code that remove the element from linked list,
public void delete(T element){
if(head != null){ // first check your header node is null or not
// create two references of your linked list
Node<T> tmp = head; // it will hold current value
Node<T> tmp1 = head.getNextRef(); // it will hold next value
while(true){ // iterate through whole linked list
if(head.getValue() == element){ // if you found element at first place
head = head.getNextRef(); // then point head to next node of it
break;
}
if(tmp1.getValue()==element){ // to remove node refer to next of tmp1
tmp.setNextRef(tmp1.getNextRef());
break;
}else{
tmp = tmp1;
tmp1 = tmp1.getNextRef();
if(tmp1==null)
break;
}
}
}
}

Categories