What is wrong with the set method of my LinkedList - java

Im trying to implement a linkedlist.. All of my methods work except for the set method. It is only supposed to change the replace the element at the given index. But after setting the element in the index it is making the rest of the elements in the list to null, can anyone point out what I'm doing wrong in the set method?
public class LArrayList<E> {
private static class Node<E> {
Node<E> next;
E data;
public Node(E dataValue) {
next = null;
data = dataValue;
}
#SuppressWarnings("unused")
public Node(E dataValue, Node<E> nextValue) {
next = nextValue;
data = dataValue;
}
public E getData() {
return data;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> nextValue) {
next = nextValue;
}
}
private Node<E> head;
private static int listCount;
public LArrayList() {
head = new Node<>(null);
listCount = 0;
}
public void add(int index, E e) throws IndexOutOfBoundsException{
if (index < 0 || index >= listCount + 1) {
throw new IndexOutOfBoundsException("Bad index, please use index within range");
}
else{
Node<E> positionTemp = new Node<>(e);
Node<E> positionCurrent = head;
for (int i = 0; i < index && positionCurrent.getNext() != null; i++) {
positionCurrent = positionCurrent.getNext();
}
positionTemp.setNext(positionCurrent.getNext());
positionCurrent.setNext(positionTemp);
listCount++;
}
}
public E set(int index, E e) throws IndexOutOfBoundsException {
if (index < 0 || index >= listCount)
throw new IndexOutOfBoundsException("Bad index, please use index within range");
Node<E> positionTemp = new Node<>(e);
Node<E> positionCurrent = head;
for (int i = 0; i < index; i++) {
positionCurrent = positionCurrent.getNext();
}
positionCurrent.setNext(positionTemp);
return positionCurrent.getData();
}
public E get(int index) throws IndexOutOfBoundsException
{
if (index < 0 || index >= listCount)
throw new IndexOutOfBoundsException("Bad index, please use index within range");
Node<E> positionCurrent = head.getNext();
for (int i = 0; i < index; i++) {
if (positionCurrent.getNext() == null)
return null;
positionCurrent = positionCurrent.getNext();
}
return positionCurrent.getData();
}
public static void main(String[] args) {
LArrayList<String> aa = new LArrayList<String>();
aa.add(0, "0");
aa.add(1, "1");
aa.add(2, "2");
aa.add(3, "3");
aa.add(4, "4");
aa.add(5, "5");
System.out.println("The contents of AA are: " + aa);
aa.set(0, "a");
System.out.println("The contents of AA are: " + aa);
System.out.println(aa.get(0));
System.out.println(aa.get(1));
System.out.println(aa.get(2));
System.out.println(aa.get(3));
System.out.println(aa.get(4));
System.out.println(aa.get(5));
//OUTPUT IS: The contents of aa are: [0][1][2][3][4][5]
//The contents of AA are: [a][b][c][d][e]
//a
//A
//null
//null
//null
//null
}
}

After a quick look over your code:
positionCurrent.setNext(positionTemp);
Don't you need to also link positionTemp to the element after it?

First get the item just before current index:
for (int i = 0; i < index; i++) {
positionCurrent = positionCurrent.getNext();
}
You are missing a link between currently set item and rest of your list, Establish that by:
positionTemp.setNext(positionCurrent.getNext().getNext());
positionCurrent.setNext(positionTemp);
And return
positionCurrent.getNext().getData()
Hope it helps.

ok, so you have many problems in your code, i will help you with some but not all.
I really advise you to use Eclipse debugger(If you use eclipse), check this out:
http://www.vogella.com/tutorials/EclipseDebugging/article.html
First of all, the reason that your whole list is null after a set is that your index is 0 than you use a for loop that does nothing(cause the index is 0), so in the line after that:
positionCurrent.setNext(positionTemp);
You are setting head's next to be positionTemp, and than you are loosing the rest of the list cause you are not setting next for postionTemp(postionTemp next is null)
second, when you are adding the first item to the list, or when the list is empty and you are adding something, you need to make this new node the list's head, otherwise your list head will always be null.
third, when you want to print list, you cant use:
System.out.println("The contents of AA are: " + aa);
You need to do this instead:
Node<E> head = aa.head;
while(head != null){
system.out.println(head.data)
}
It looks like you have more bugs on your code, so i simply advise you use debugger.
Good luck

Related

How to create a linked list in java without importing linked lists

i am a CS student in college and i am having trouble with this project where i am supoosed to create a linked list using nodes without importing linked lists, as well as doing a some methods with the list. i am a beginner when it comes to coding, so assume i know nothing, because that is probably the case lol.
import java.io.*;
import java.lang.*;
public class List {
public int listCount = 0;
public char[] linkedList;
public List() throws FileNotFoundException {
}
public List(char[] array) throws FileNotFoundException {
if (array.length == 1) {
Node head = new Node(array[0]);
} else if (array.length > 1) {
Node head = new Node(array[0]);
Node traverse = head;
for (int i = 1; i < array.length; i++) {
while (traverse.nextNode != null) {
traverse = traverse.nextNode;
}
traverse.nextNode = new Node(array[i]);
listCount++;
}
}
}
public List(String w) throws FileNotFoundException {
char[] array2 = new char[w.length()];
for (int i = 0; i < w.length(); i++) {
array2[i] = w.charAt(i);
}
List str = new List(array2);
}
/* Find the character at a index
#param int index
return the character at the chosen index
*/
public char charAt(int index) throws IndexOutOfBoundsException {
char results = linkedList[0];
if (index < linkedList.length && index >= 0) {
results = linkedList[index];
}
return results;
}
public String concat(int index1, int index2) {
return null;
}
/* Determine if the list is empty
return whether the given conditions are true or false
*/
public boolean isEmpty() {
for (int i = 0; i < linkedList.length; i++) {
if (!linkedList.equals(null)) {
System.out.println("This list is not empty");
return false;
}
}
System.out.println("List is empty");
return true;
}
/* Determine the size of the list
return the size of the list
*/
public int size() {
return listCount;
}
/* Create a new String between 2 index's including the start and end index
#param beginIndex is the starting point of the new String
#endIndex is the ending point of new String
return the new String
*/
public String subString(int beginIndex, int endIndex) {
return null;
}
public void insert(Object x) throws IndexOutOfBoundsException {
if (listCount > 100 || listCount < 0) {
throw new IndexOutOfBoundsException("Bag is too large");
} else {
this.linkedList[listCount] = (char) x;
listCount++;
}
}
}
i appreciate any help or pointers ahead of time. we are using a separate node, helper, and driver class as well as a .txt file to assign into my list. i am stuck on the concat and substring methods too, but i want to make sure i am getting the framework correct first. thank you again.
If i understand your question correctly, you are asking how to access a specific type without importing it.
Imports are required to identify which type is referenced when it is used by its simple name. To reference a type without declaring it in the imports you need to use its fully qualified name. For instance
java.util.List<String> someList = new java.util.ArrayList<>();
works without importing List and ArrayList because by declaring the package the class is in it is clear which class is being referenced.
I'll try to do the code later, but here is a book that i found that may help you.
https://cin.ufpe.br/~grm/downloads/Data_Structures_and_Algorithms_in_Java.pdf
I bought a book about DATA STRUCTURE from Pearson company, and it's really a good book, but i don't remember much, it's something like this, that i did in a hurry:
public class List {
private Node head = null;
private Node foot = null;
private Node newNode = null;
private Node auxNode = null;
public List() {
this.head = new Node();
this.foot = new Node();
}
public class Node {
private int adress;
private Node nextNode;
}
public void add(int value) {
this.newNode = new Node();
newNode.adress = value;
if (head == null) {
// Head of the list receive the values of the NEW NODE, so the head of the list
// is not null enymore
head = newNode;
head.nextNode = null;
} else {
// In this case Head is not null
/*The auxiliary node will receive the head and the new Node will become the new Head from the list*/
auxNode = new Node();
auxNode = head;
/*
while(auxNode.nextNode != null ) {
}
auxNode = head;
//head of the list is empty, so we can add the new node
head = newNode;//Here the new node is empty because was transfered to the head
head.nextNode = auxNode; //The head of the list receive the old node that used to be the head
if (head.nextNode == null) {
head.nextNode = newNode;
} else if (head.nextNode != null) {
}*/
}
}
}
```
I hope this help you to get some lead

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.

Java LinkedList inserting Object at index

I am having a bit of trouble understanding how to place an object in a linked.
In this case, if there is already an object at the specific index, it won't replace it (that is for another method). I guess I am having trouble understanding how to get to a specific index, retrieve the data from that index, and then either put data there and connect the nodes or tell the user there is already an object there.
Here is my code:
public class CourseList {
private Coursenode head;
int currentSize;
public void insertAtIndex(Course c, int index) {
Coursenode insert =new Coursenode(c,head);
Coursenode temp = new Coursenode();
if (index > currentSize - 1 || index < 0) {
throw (new IndexOutOfBoundsException());
}
for(int x = 0; x < index; x++) {
if (insert.getNext()!= null) {
temp = insert;
insert.setNext(insert);
insert.setData(temp.getData());
}
if (insert.getNext() == null && x == index) {
insert.setNext(insert.getNext());
}
if (insert.getNext() != null && x == index) {
System.out.println("There is already a Course at that Index");
}
}
}
}
Here is the inner class Coursenode:
public class Coursenode {
private Course data;
private Coursenode next;
public Coursenode() {
this.data = null;
this.next = null;
}
public Coursenode(Course course, Coursenode next) {
this.data=course;
this.next= next;
}
public Coursenode(Coursenode x) {
this.data = x.getData();
this.next = x.getNext();
}
public Course getData() {
return data;
}
public void setData(Course data) {
this.data = data;
}
public Coursenode getNext() {
return next;
}
public void setNext(Coursenode next) {
this.next = next;
}
//Clone method
public void clone(Coursenode new_cn){
new_cn = new Coursenode (this.getData(),this.getNext());
}
}
Any thought would be appreciated, I suspect I am getting lost within the head reference between nodes but I can't quite figure out how to solve the problem.
There are three ways (assuming positive index values) to make an insertion at an index in a linked list:
At the head (index == 0)
After the tail (index >= currentSize)
In the middle (at an occupied index) (index > 0 && index < currentSize)
There may be a tendency to think that inserting at the tail is another case, but later we'll see that insertion at the tail is the same as an insertion in the middle, because the tail will be slid forward.
If the insertion is at the head, you need to set the next of the inserted node to the old head and then set head to the inserted node:
private void insertAtHead(Course course) {
Coursenode insertedNode = new Coursenode(c, head);
head = insertedNode;
}
If the insertion occurs past the tail, a common way of dealing with this is to throw some sort of exception, such as an IndexOutOfBoundsException:
throw new IndexOutOfBoundsException("Cannot insert course after the tail of the course list");
If the insertion occurs at an occupied index, the existing node (and all nodes after the existing node) must be pushed forward. This means that the next of the inserted node must be set to the node that currently occupies the index and the next of the node previous to the node at the current index must be set to the inserted node. In essence, the inserted node is fused into the list. To do this, the list must be traversed until the occupied node is found:
private void insertAtOccupied(Course course, int index) {
Coursenode previous = null;
Coursenode current = head;
for (int i = 1; i <= index; i++) {
// Track the previous and current nodes
// previous = node at i - 1
// current = node at i
previous = current;
current = current.next;
}
Coursenode insertedNode = new Coursenode(c, current.next);
previous.next = insertedNode;
}
Pulling these cases together, we can create the following logic:
public void insertAt(Course course, int index) {
if (index == 0) {
insertAtHead(course);
}
else if (index >= currentSize) {
throw new IndexOutOfBoundsException("Cannot insert course after the tail of the course list");
}
else if (index > 0 && index < currentSize) {
insertAtOccupied(course, index);
}
}
First of all in a linkedlist if
index < linkedlistsize
then there is an object already in a linkedlist. If you have a null node in node.next that how you know you have reached the end of your linked list.
public class CourseList {
private Coursenode head;
int currentSize;
public void insertAtIndex(Course c, int index) {
Coursenode insert =new Coursenode(c,head);
Coursenode temp = new Coursenode();
if (index > currentSize - 1 || index < 0) {
throw (new IndexOutOfBoundsException());
}
//tempnode = head;
for(int x=1; x< index;x++) {
//tempnode = tempnode.next;
}
//nodeatindex = tempnode;
//you can get details of the node
}
Hope this helps!

Creating an edit method using a singly linked list

Is there any way I can edit a specific node's data within a linked list? I started writing a method:
public void edit(int index, String data) {
Node pre = head;
Node temp = null;
for(int i=1; i <= index; i++) {
temp = pre;
pre = pre.next();
}
temp.next(new Node(data));
pre.data(data);
}
I have four nodes in my list, I used this method to edit the node at index 1 in the list, however now when I print out all elements in the list it only shows nodes at index 0 and 1, and 2-3 do not appear. Any hints on whats going wrong here?
public void edit(int index, String data) {
Node pre = head;
Node temp = null;
for(int i=1; i <= index; i++) {
temp = pre;
pre = pre.next();
}
Node newNote = new Node(data);
temp.next = newNote;
newNote.next = pre.next;
}
You should also handle the some specific situations. For example: This code doesn't work for index = 0. And This code throws exceptions for linked list size when be 0. And This code also throws exceptions when index bigger then linked list size. And things like that
public void edit(int index, String data) {
if (index==0) {
head.data(data);
return;
}
if (index < 0 || index > size()) {
throw new IndexOutOfBoundsException("Index out of bounds.");
}
Node pre = head;
Node temp = null;
for(int i=1; i <= index; i++) {
temp = pre;
pre = pre.next;
}
Node newNode = new Node(data);
temp.next(newNode);
newNode.next(pre.next);
}
#Mustafa Akıllı Something like this?

linkedlist implementation add method

I'm implementing a linked list for a course online, and there seems to be something wrong with my add function. When I try to add the first element, the Eclipse prints null, and for a second element Eclipse shows an error. (I'm assuming because the first element was never added, so there can't be a second one.)
This is the implementation of my linked list:
package textgen;
import java.util.AbstractList;
public class MyLinkedList<E> extends AbstractList<E> {
LLNode<E> head;
LLNode<E> tail;
int size;
/** Create a new empty LinkedList */
public MyLinkedList() {
size = 0;
head = new LLNode<E>();
tail = new LLNode<E>();
head.next = tail;
tail.prev = head;
}
/**
* Appends an element to the end of the list
* #param element The element to add
*/
public boolean add(E element )
{
add(size, element);
return false;
}
/** Get the element at position index
* #throws IndexOutOfBoundsException if the index is out of bounds. */
public E get(int index) throws IndexOutOfBoundsException
{
if(index >= this.size){
throw new IndexOutOfBoundsException("Your index is out of bounds!");
}
LLNode<E> lGet = head;
for(int i = 0; i < index + 1; i++){
lGet = lGet.next;
}
return lGet.data;
}
public void printList(){
LLNode lTemp = head;
while(lTemp.next != tail){
System.out.println(lTemp.next.data);
lTemp = lTemp.next;
}
}
/**
* Add an element to the list at the specified index
* #param The index where the element should be added
* #param element The element to add
*/
public void add(int index, E element ) throws IndexOutOfBoundsException
{
if(index > this.size){
throw new IndexOutOfBoundsException("Oops! Out of bounds!");
}
else{
LLNode<E> nAdd = new LLNode<E>(element);
LLNode<E> nIt = null;
if(index <= size/2) // if the index is closer to the start from the beginning of the list
{
nIt = head;
for(int i = 0; i < index + 1; i++){
nIt = nIt.next;
}
}
else {
nIt = tail;
for(int i = this.size; i > index; i--){
nIt = nIt.prev;
}
}
nIt.prev.next.prev = nAdd;
nAdd.next = nIt.prev.next;
nIt.prev.next = nAdd;
nAdd.prev = nIt.prev;
size++;
}
}
/** Return the size of the list */
public int size()
{
return size;
}
/** Remove a node at the specified index and return its data element.
* #param index The index of the element to remove
* #return The data element removed
* #throws IndexOutOfBoundsException If index is outside the bounds of the list
*
*/
public E remove(int index)
{
// TODO: Implement this method
size--;
return null;
}
/**
* Set an index position in the list to a new element
* #param index The index of the element to change
* #param element The new element
* #return The element that was replaced
* #throws IndexOutOfBoundsException if the index is out of bounds.
*/
public E set(int index, E element)
{
// TODO: Implement this method
return null;
}
}
class LLNode<E>
{
LLNode<E> prev;
LLNode<E> next;
E data;
public LLNode(){
this.data = null;
this.prev = null;
this.next = null;
}
public LLNode(E e)
{
this.data = e;
this.prev = null;
this.next = null;
}
}
This is the main:
package textgen;
public class fixAdd {
public static void main(String [] Arg){
MyLinkedList<String> ll = new MyLinkedList<String>();
ll.add(0, "happy");
ll.add(1, "gilda");
System.out.println(ll);
}
}
And this is the error printed:
Exception in thread "main" java.lang.NullPointerException
at textgen.MyLinkedList.get(MyLinkedList.java:57)
at java.util.AbstractList$Itr.next(Unknown Source)
at java.util.AbstractCollection.toString(Unknown Source)
at java.lang.String.valueOf(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at textgen.fixAdd.main(fixAdd.java:11)
I've gone over my add method a number of times, and compared it to other implementations I found online, and everything seems in order. I'm totally confused and would appreciate any help. Thanks!
You should try to implement a simpler add first, instead of doing the size / 2 optimization.
There are several problems with your code:
don't create dummy nodes at initialization, initialize them with null
your loop in get method should be for(int i = 0; i < index; i++)
your aren't updating the size in your add method
EDIT: Changed add method to cover all cases:
public void add(int index, E element)
{
if (index > size)
{
throw new IndexOutOfBoundsException("Oops! Out of bounds!");
}
LLNode<E> node = new LLNode<E>(element);
//Add first and last
if(size == 0)
{
head = tail = node;
}
else
{
//Add first
if(index == 0)
{
node.next = head;
head.prev = node;
head = node;
}
//Add last
else if(index == size)
{
node.prev = tail;
tail.next = node;
tail = node;
}
//Add between
else
{
LLNode<E> current = this.head;
for(int i = 0; i < index; i++)
{
current = current.next;
}
node.next = current;
node.prev = current.prev;
current.prev.next = node;
}
}
size++;
}
Multiple issues with this implementation:
You're setting both head and tail to be empty Nodes when you initialize the list (constructor). You shouldn't do that, it makes your list to be of size two with two null elements.
The exception is thrown from the printing in the main which, in turn, calls your get() method (by calling AbstractList.toString())
In add(E element) you're calling add(size, element); and you pass the size as the index, later on you check if if(index > this.size) which is practically asking if size > size - makes no sense.
In remove() implementation you just decrease the size - this is not good enough, you should also move the tail backwards (and if the list is of size 1 - handle the head as well).
The is the main issue: the logic of insertion in the following lines is incorrect:
nIt.prev.next.prev = nAdd;
nAdd.next = nIt.prev.next;
nIt.prev.next = nAdd;
nAdd.prev = nIt.prev;
Two suggestions:
Don't inherit from AbstractList - after all you're creating your own implementation
Start simple, forget about tail or about trying to insert from the end for better efficiency. Only after you have a simple implementation working - try to improve it.
Try the following code:
public void insert(int index, T item)
{
if(index == size())
{
add(item);
}
else if(index == 0)
{
MyNode<T> temp = new MyNode<T>();
temp.data = item;
temp.next = head;
head.previous = temp;
head = temp;
count++;
}
temp = head;
for(int i = 0; i < index-1; i++)
{
temp = temp.next;
MyNode<T> myNode = new MyNode<T>();
myNode.data = item;
myNode.next = temp.next;
temp.next = myNode;
count++;
}
}

Categories