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!
Related
My whole code to try to get the las three nodes of a linked list is:
Node class:
package com.company;
public class Node {
public int data;
public Node nextNode;
public Node(int data) {
this.data = data;
this.nextNode = null;
}
public int getData() {
return data;
}
}
Linked list class;
package com.company;
public class LinkedList {
public Node head;
public int size;
public LinkedList() {
this.head = null;
this.size = 0;
}
public void add(int data) {
Node node = new Node(data);
if (head == null) {
head = node;
} else {
Node currentNode = head;
while(currentNode.nextNode != null) {
currentNode = currentNode.nextNode;
}
currentNode.nextNode = node;
}
size++;
}
public void printData() {
Node currentNode = head;
while(currentNode != null) {
int data = currentNode.getData();
System.out.println(data);
currentNode = currentNode.nextNode;
}
}
public void printLastThree(){
Node currentNode = head;
int i = this.size - 3;
while(i <= this.size) {
int data = currentNode.getData();
System.out.println(data);
currentNode = currentNode.nextNode;
i++;
}
}
}
Main class:
package com.company;
public class Main {
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.add(1);
ll.add(2);
ll.add(3);
ll.add(4);
ll.add(5);
ll.add(6);
ll.add(7);
ll.add(8);
ll.add(9);
ll.add(10);
ll.add(11);
ll.add(12);
ll.printData();
System.out.println();
ll.printLastThree();
}
}
As you can see, in the linked list class I try to print the last three nodes of the linked list with the printLastThree() method, but in console I just get:
1
2
3
4
And I would like to get:
10
11
12
Can you say me what I am doing wrong?
I try in printLastThree() method to get the total size of the linked list and substract 3 positions, and then get to the total size of the linked list, but that doesn't work.
Thanks.
Once can see from your code that currentNode starts as the head node, and its value gets printed in the first iteration of the loop. This is not what you want.
You'll first have to skip nodes, which do not get printed. You already calculated how many such nodes need to be skipped (this.size - 3), so you only need to add the loop to actually skip that many nodes:
public void printLastThree(){
Node currentNode = head;
// First SKIP nodes (not to be printed)
for (int i = size - 3; i > 0; i--) {
currentNode = currentNode.nextNode;
}
// ...and only then start printing
while (currentNode != null) {
int data = currentNode.getData();
System.out.println(data);
currentNode = currentNode.nextNode;
}
}
You can also do it with one loop, and make the printing conditional on the current index:
public void printLastThree(){
Node currentNode = head;
for (int i = 0; i < size; i++) {
if (i >= size - 3) { // Are we at the last three nodes?
int data = currentNode.getData();
System.out.println(data);
}
currentNode = currentNode.nextNode;
}
}
the bug is in printLastThree().
You need to move the currentNode from head to position: size-3; But don't print it just yet.
Then after that, move again from size-3 to size-1 and during this move, print it out.
try 2 while loops. Later you can also make it into 1 while loop from start to end with if condition whether to print or not.
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.
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?
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
I want to maintain order of the elements being added in a list. So, I used a LinkedList in Java.
Now I want to be able to swap two elements in the linked list. First of all, I cannot find an elementAt() for LinkedList. Also, there is no way to add element at a specified position.
There is a Collections.swap(List<?> list, int i, int j) that you can use to swap two elements of a List<?>. There's also LinkedList.get(int index) and LinkedList.add(int index, E element) (both are methods specified by interface List). All of these operations will be O(N) since a LinkedList does not implements RandomAccess.
Check out the Javadocs for LinkedList
To find an element at an index use get(int index)
To place an element at a certain index use set(int index, Object element)
If you are writing your own LinkedList class for exercise (i.e. for a project or school), try making two temporary Object variables and two ints to hold their position in the List. Then, use add(int, Object) to add the first in the 2nd position, second in the 1st position.
public class SwapNode {
public static Node head;
public static void main(String[] args) {
SwapNode obj = new SwapNode();
obj.insertAtEnd(5);
obj.insertAtEnd(6);
obj.insertAtEnd(4);
obj.insertAtEnd(7);
obj.insertAtEnd(3);
obj.insertAtEnd(8);
obj.insertAtEnd(2);
obj.insertAtEnd(9);
obj.insertAtEnd(1);
obj.print(head);
System.out.println("*** Swapped ***");
obj.swapElementValue(4, 2);
}
public void swapElementValue(int value1, int value2) {
if (value1 == value2) {
System.out.println("Values same, so no need to swap");
return;
}
boolean found1 = false, found2 = false;
Node node = head;
while (node != null && !(found1 && found2)) {
if (node.data == value1) {
node.data = value2;
found1 = true;
node = node.next;
continue;
}
if (node.data == value2) {
node.data = value1;
found2 = true;
node = node.next;
continue;
}
node = node.next;
}
if (found1 && found2) {
print(head);
} else {
System.out.println("Values not found");
}
}
public void insertAtEnd(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
return;
}
Node temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = newNode;
}
public void print(Node head) {
Node temp = head;
while(temp != null) {
System.out.print(temp.data);
temp = temp.next;
}
System.out.println();
}
static class Node {
private int data;
public Node next;
public Node(int data) {
this.data = data;
}
}
}
add
Does this what you want?
If you want to keep the list in a sorted state, why not just insert the element with addfirst
and then sort the list using Collections.sort
Take a look at ArrayList , this class will both maintain the insertion order and provide O(1) random access.
// I tried to reduce time complexity here, in 3 while loops (get() and set() use 4 while loop)
void swapAt(int index1, int index2){ // swapping at index
Node tmp = head;
int count=0;
int min, max; // for future reference to reduce time complexity
if(index1<index2){
min = index1;
max = index2;
}
else{
min = index2;
max = index1;
}
int diff = max - min;
while(min!=count){
tmp= tmp.next;
count++;
}
int minValue = tmp.data;
while(max!=count){
tmp= tmp.next;
count++;
}
int maxValue = tmp.data;
tmp.data = minValue;
tmp = head;
count =0;
while(min!=count){
tmp= tmp.next;
count++;
}
tmp.data = maxValue;
}