LinkedList from scratch, replacing a node - java

I was given an assignement to create a LinkedList from scratch, I've figured how to code a method that add a node at the end of the list but I still can't figure how to replace a node. Here is what I have so far:
public boolean replace(int element, int index) {
Node temp= new Node(pElement);
Node current = getHead();
if (!isEmpty()) {
for (int i = 0; i < index && current.getNext() != null; i++) {
current = current.getNext();
}
temp.setNext(noeudCourant.getNext());
noeudCourant.setNext(temp);
listCount++;
return true;
}
return false;
}
Using aNode.replace(10, 4) on "0 1 2 3 4 5 6 7 8 9 10"
will make it into
[0]->[1]->[2]->[3]->[4]->[10]->[5]->[6]->[7]->[8]->[9]->[10]
but I want:
[0]->[1]->[2]->[3]->[10]->[5]->[6]->[7]->[8]->[9]->[10]
Any help is appreciated.
[edit]I already have a working method setData() but the assignment I have forbid me to use it. What I want is basically this:
http://i.imgur.com/oOVYCvc.png

Here is a simple solution for your question:
package linkedlist;
class Node {
public Node next = null;
public int element;
public Node(int el) {
element = el;
}
}
class LinkedList {
public Node first = null;
public void add(Node node) {
if (first == null) {
first = node;
} else {
// Traverse to the last
Node cursor = first;
while (cursor.next != null) {
cursor = cursor.next;
}
cursor.next = node;
}
}
public void add(int[] elements) {
int len = elements.length;
for (int i=0;i < len;i++) {
add(new Node(elements[i]));
}
}
public boolean replace(int element, int index) {
Node cursor = first;
Node prev = null;
while (cursor != null && index >= 0) {
index--;
prev = cursor;
cursor = cursor.next;
}
if (index > 0) return false;
if (prev != null)
prev.element = element;
return true;
}
public void displayAll() {
Node cursor = first;
while (cursor != null) {
System.out.print(cursor.element + " ");
cursor = cursor.next;
}
System.out.println();
}
}
public class Main {
public static void main(String[] args) {
// Prepare elements
LinkedList linkedList = new LinkedList();
linkedList.add(new int[]{0,1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
println("Display the initial linked list content:");
linkedList.displayAll();
println("After replace:");
linkedList.replace(10, 4);
linkedList.displayAll();
println("Done");
}
static void println(String msg) {
System.out.println(msg);
}
}

If you really want to replace the Node and do not delete it then here is how you should be writing your replace() function:
public boolean replace(int element, int index) {
Node head = getHead();
int counter = 0;
while(null != head && counter++ < index - 1) {
head = head.getNext();
}
if(null == head || null == head.getNext()) return false;
Node newNode = new Node(element);
newNode.setNext(head.getNext().getNext());
head.setNext(newNode);
return true;
}
Here, I'm assuming that you have setNext() method in your Node class to set the link.
Also note that here it is assumed that you'll never replace head itself i.e. you'll never replace the element at index 0 or else you'll have to return the new head from the function.

Try below code. I have written the logic in comments wherever required.
public boolean replace(int element, int index) {
Node temp= new Node(pElement);
Node current = getHead();
if (!isEmpty()) {
//Run for loop one less than index value.
for (int i = 0; i < index -1 && current.getNext() != null; i++) {
current = current.getNext();
}
// At this point current points to element 3.
// Set next element of node 4 as a next element of new element 10.
temp.setNext(current.getNext().getNext());
// at this point we have two references for element 5 like below
// [0]->[1]->[2]->[3]->[4]->[5]->[6]->[7]->[8]->[9]->[10]
// [10]->[5]->[6]->[7]->[8]->[9]->[10]
// Set null to next element of of element 4 to remove reference to
// element 5
current.getNext().setNext(null);
// At this point we have two list as below:
// [0]->[1]->[2]->[3]
// [10]->[5]->[6]->[7]->[8]->[9]->[10]
// Set new element as next of current element (current element is 3)
current.setNext(temp);
// here we have replaced the element 4 with element 10
listCount++;
return true;
}
return false;
}

Related

Remove method for LinkedList

So, I am trying to write two overloaded remove methods for LinkedList class, where one takes an index of an element that needs to be removed and another one that takes Object that needs to be removed. But when I try to make a LinkedList of integer and call the latter method, method that takes in index is called instead. Is there any way around this??
(PS. I know you can just change the name of the method, but I am given an interface file that requires me to write overloaded methods)
public E remove(int index) {
for (int i = 0; i < index;i++) {
curNode = curNode.next();
}
if (curNode == head && curNode == tail) {
head = null;
tail = null;
}
else {
URNode sucNode = curNode.next();
URNode prevNode = curNode.prev();
if (sucNode != null)
sucNode.setPrev(prevNode);
else {
prevNode.setNext(null);
tail = prevNode;
}
if (prevNode != null)
prevNode.setNext(sucNode);
else {
sucNode.setPrev(null);
head = sucNode;
}
}
numElements--;
return null;
}
public boolean remove(Object o) {
URNode curNode = head;
for (int i = 0; i < numElements;i++) {
if (curNode.element() == o) {
remove(i);
return true;
}
curNode = curNode.next();
}
return false;
}
public static void main(String args[]){
LinkedList intList = new LinkedList();
intList.add(1);
intList.add(2);
intList.add(3);
intList.remove(1); //I want this to remove node with element 1, instead of node with index of 1
//[2][3] should be returned, not [1][3]
}
intList.remove(Integer.valueOf(1)); // just make it Integer but not int

How do I insert an Item at a certain Index in a Linked List?

I am working on a project for my Data Structures class that asks me to write a class to implement a linked list of ints.
Use an inner class for the Node.
Include the methods below.
Write a tester to enable you to test all of the methods with whatever data you want in any order.
I have to create a method called "public void insertAt(int index, int item)". This method is meant to "Insert an item at position index, where index is passed to the method" I have my code for this method down below. When I execute this method nothing happens. The item that I try to add to a specific index never gets added. Does someone know what I did wrong? and How to fix it?
import java.util.Random;
import java.util.Scanner;
public class LinkedListOfInts {
Node head;
Node tail;
private class Node {
int value;
Node nextNode;
public Node(int value, Node nextNode) {
this.value = value;
this.nextNode = nextNode;
}
}
public LinkedListOfInts(LinkedListOfInts other) {
Node tail = null;
for (Node n = other.head; n != null; n = n.nextNode) {
if (tail == null)
this.head = tail = new Node(n.value, null);
else {
tail.nextNode = new Node(n.value, null);
tail = tail.nextNode;
}
}
}
public LinkedListOfInts(int[] other) {
Node[] nodes = new Node[other.length];
for (int index = 0; index < other.length; index++) {
nodes[index] = new Node(other[index], null);
if (index > 0) {
nodes[index - 1].nextNode = nodes[index];
}
}
head = nodes[0];
}
public LinkedListOfInts(int N, int low, int high) {
Random random = new Random();
for (int i = 0; i < N; i++)
this.addToFront(random.nextInt(high - low) + low);
}
public void addToFront(int x) {
head = new Node(x, head);
}
public void insertAt(int index, int item) {
Node temp = head;
Node prev = null;
int i = 0;
for (Node ptr = head; ptr != null; ptr = ptr.nextNode) {
prev = temp;
temp = temp.nextNode;
i++;
}
if (index == i) {
Node newItem = new Node(item, null);
prev.nextNode = newItem;
newItem.nextNode = temp;
}
}
public String toString() {
String result = "";
for (Node ptr = head; ptr != null; ptr = ptr.nextNode) {
if (!result.isEmpty()) {
result += ", ";
}
result += ptr.value;
}
return "[" + result + "]";
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
LinkedListOfInts list = new LinkedListOfInts(10, 1, 20);
boolean done = false;
while (!done) {
System.out.println("1. Insert At");
System.out.println("2. toString");
switch (input.nextInt()) {
case 1:
System.out.println("Insert an Item to a certain Index on the List");
list.insertAt(input.nextInt(), input.nextInt());
break;
case 2:
System.out.println("toString");
System.out.println(list.toString());
break;
}
}
}
}
There are a few issues, but you are most of the way there, you simply need to move the if statement if (index == i) {Node newItem... } inside of your 'for' loop like this:
public void insertAt(int index, int item) {
Node temp = head;
Node prev = null;
int i = 0;
for (Node ptr = head; ptr != null; ptr = ptr.nextNode) {
prev = temp;
//Make sure the next node is not null
if (temp.nextNode != null) {
temp = temp.nextNode;
}
//Move the if check here inside the for loop, but before i++
if (index == i) {
Node newItem = new Node(item, null);
prev.nextNode = newItem;
//Make sure the next node is not null
if (temp.nextNode != null) {
newItem.nextNode = temp;
}
}
//now advance the index after the above
i++;
}
}
Note that your code had an error, which has been fixed by checking that the next node is not null.
We can see the updated method works by inserting 999 after index 2:
1. Insert At
2. toString
1
Insert an Item to a certain Index on the List
2 999
1. Insert At
2. toString
2
toString
[5, 18, 8, 999, 11, 11, 1, 19, 3, 1, 10]
1. Insert At
2. toString
If you want the item to be inserted at index 2 instead, then adjust the order and put the if statement before prev = temp;

Having some trouble using a Linked List and passing elements to the Node

In this specific instance, it takes into account two occasions. One where I'm trying to place a node in the beginning of the Linked List and one where I'm trying to place it in the middle or at the end. Here is my Node Class. If you look at my INSERT method, the part that is not working is:
Node newNode = new Node();
newNode.setExponent(element);
class Node {
private int coefficient;
private int exponent;
private Node link;
// Constructor: Node()
Node(int c, int e) {
// Sets coefficient to c, exponent to e, and link to null
coefficient = c;
exponent = e;
link = null;
}
// Inspectors: getCoefficient(), getExponent(), getLink()
public int getCoefficient() {
// Returns coefficient
return coefficient;
}
public int getExponent() {
// Returns exponent
return exponent;
}
public Node getLink() {
// Returns link
return link;
}
// Modifiers: setCoefficient(), setExponent(), setLink()
public void setCoefficient(int c) {
// Sets coefficient to c
coefficient = c;
}
public void setExponent(int e) {
// Sets exponent to e
exponent = e;
}
public void setLink(Node n) {
// Sets link to n
link = n;
}
}// Ends Node Class
Here is where I'm trying to insert to my Linked List along with some other methods in the class that should help give you an idea of how my code looks.
class List {
private Node head; // Points to first element of the list
private int count; // number of elements in the list
// Constructor:
List() {
// Sets head to null and count to zero
head = null;
count = 0;
}
// Inspectors:
// Returns the number of elements in the list
public int size() {
return count;
}
// Modifiers:
// Inserts element at index in the list. Returns true if successful
public boolean insert(int index, Node element) {
if (index < 0 || index > count)return false;
if (index == 0) {
Node newNode = new Node();
newNode.setExponent(element);
count++;
newNode.setLink(head);
head = newNode;
return true;
}
Node walker = head;
for (int i = 1; i < (index - 1); i++)
walker = walker.getLink();
Node newNode = new Node();
newNode.setExponent(element);
newNode.setLink(walker.getLink());
walker.setLink(newNode);
count++;
return true;
}
Try this:
Assumption: You are trying to insert a Node element into the index of LinkedList
Your insert method with modification.
public boolean insert(int index, Node element) {
//if (index < 0 || index > count)
if (index < 0 || index > count + 1) return false;
if(head == null) {
head = element;
return true;
}
if (index == 0) {
//Node newNode = new Node();
//newNode.setExponent(element);
count++;
element.setLink(head);
//newNode.setLink(head);
head = element;
//head = newNode;
return true;
}
Node walker = head;
//for (int i = 0; i < (index - 1); i++)
for (int i = 1; i < index; i++) {
walker = walker.getLink();
}
//Node newNode = new Node();
//newNode.setExponent(element);
element.setLink(walker.getLink());
//newNode.setLink(walker.getLink());
//walker.setLink(newNode);
walker.setLink(element);
count++;
return true;
}
Sample Test Case:
print method:
void print() {
Node travel = head;
while(travel!= null) {
System.out.println(travel.getExponent() + " " + travel.getCoefficient());
travel = travel.getLink();
}
}
Main method:
public static void main(String args[]) {
Node n1 = new Node(1,2);
List l = new List();
l.insert(0,n1);
Node n2 = new Node(3,2);
l.insert(1,n2);
Node n3 = new Node(4,5);
l.insert(0,n3);
l.print();
}

Can someone tell me what i'm doing wrong? Counting and looping through LinkedList

My code is as follows:
import net.datastructures.Node;
public class SLinkedListExtended<E> extends SLinkedList<E> {
public int count(E elem) {
Node <E> currentNode = new Node <E>();
currentNode = head;
int counter = 0;
for (int i = 0; i<size; i++){
if (currentNode == null) {
return 0; //current is null
}
else if (elem.equals(currentNode.getElement())){
counter++;
currentNode = currentNode.getNext();
}
}
return counter;
}
public static void main(String[] args) {
SLinkedListExtended<String> x = new SLinkedListExtended<String>();
x.insertAtTail("abc");
x.insertAtTail("def");
x.insertAtTail("def");
x.insertAtTail("xyz");
System.out.println(x.count("def")); // should print "2"
//x.insertAtTail(null);
x.insertAtTail("def");
//x.insertAtTail(null);
System.out.println(x.count("def")); // should print "3"
//System.out.println(x.count(null)); // should print "2"
}
}
The method count is supposed to return the number of the amount of times a given element, elem is found in a list. I have written this loop but only get a return of 0 every time. A nullpointerexception is also thrown.
Edit: SLinkedList SuperClass
import net.datastructures.Node;
public class SLinkedList<E> {
protected Node<E> head; // head node of the list
protected Node<E> tail; // tail node of the list (if needed)
protected long size; // number of nodes in the list (if needed)
// default constructor that creates an empty list
public SLinkedList() {
head = null;
tail = null;
size = 0;
}
// update and search methods
public void insertAtHead(E element) {
head = new Node<E>(element, head);
size++;
if (size == 1) {
tail = head;
}
}
public void insertAtTail(E element) {
Node<E> newNode = new Node<E>(element, null);
if (head != null) {
tail.setNext(newNode);
} else {
head = newNode;
}
tail = newNode;
size++;
}
public static void main(String[] args) { // test
}
}
It seems you missed to go to the next node if non of both condition match.
public int count(E elem) {
Node <E> currentNode = new Node <E>();
currentNode = head;
int counter = 0;
for (int i = 0; i<size; i++){
if (currentNode == null) {
return 0; //current is null
}
else if (elem.equals(currentNode.getElement())){
counter++;
}
currentNode = currentNode.getNext();
}
return counter;
}
MrSmith's answer nails it, I think. I would not use size for the loop but take the fact that there is no next as bottom. Of course your count method then has to return the counter in all cases and not 0.

deleteBack java program

I am doing some exercises on practice-it website. And there is a problem that I don't understand why I didn't pass
Write a method deleteBack that deletes the last value (the value at the back of the list) and returns the deleted value. If the list is empty, your method should throw a NoSuchElementException.
Assume that you are adding this method to the LinkedIntList class as defined below:
// A LinkedIntList object can be used to store a list of integers.
public class LinkedIntList {
private ListNode front; // node holding first value in list (null if empty)
private String name = "front"; // string to print for front of list
// Constructs an empty list.
public LinkedIntList() {
front = null;
}
// Constructs a list containing the given elements.
// For quick initialization via Practice-It test cases.
public LinkedIntList(int... elements) {
this("front", elements);
}
public LinkedIntList(String name, int... elements) {
this.name = name;
if (elements.length > 0) {
front = new ListNode(elements[0]);
ListNode current = front;
for (int i = 1; i < elements.length; i++) {
current.next = new ListNode(elements[i]);
current = current.next;
}
}
}
// Constructs a list containing the given front node.
// For quick initialization via Practice-It ListNode test cases.
private LinkedIntList(String name, ListNode front) {
this.name = name;
this.front = front;
}
// Appends the given value to the end of the list.
public void add(int value) {
if (front == null) {
front = new ListNode(value, front);
} else {
ListNode current = front;
while (current.next != null) {
current = current.next;
}
current.next = new ListNode(value);
}
}
// Inserts the given value at the given index in the list.
// Precondition: 0 <= index <= size
public void add(int index, int value) {
if (index == 0) {
front = new ListNode(value, front);
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = new ListNode(value, current.next);
}
}
public boolean equals(Object o) {
if (o instanceof LinkedIntList) {
LinkedIntList other = (LinkedIntList) o;
return toString().equals(other.toString()); // hackish
} else {
return false;
}
}
// Returns the integer at the given index in the list.
// Precondition: 0 <= index < size
public int get(int index) {
ListNode current = front;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.data;
}
// Removes the value at the given index from the list.
// Precondition: 0 <= index < size
public void remove(int index) {
if (index == 0) {
front = front.next;
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = current.next.next;
}
}
// Returns the number of elements in the list.
public int size() {
int count = 0;
ListNode current = front;
while (current != null) {
count++;
current = current.next;
}
return count;
}
// Returns a text representation of the list, giving
// indications as to the nodes and link structure of the list.
// Detects student bugs where the student has inserted a cycle
// into the list.
public String toFormattedString() {
ListNode.clearCycleData();
String result = this.name;
ListNode current = front;
boolean cycle = false;
while (current != null) {
result += " -> [" + current.data + "]";
if (current.cycle) {
result += " (cycle!)";
cycle = true;
break;
}
current = current.__gotoNext();
}
if (!cycle) {
result += " /";
}
return result;
}
// Returns a text representation of the list.
public String toString() {
return toFormattedString();
}
// ListNode is a class for storing a single node of a linked list. This
// node class is for a list of integer values.
// Most of the icky code is related to the task of figuring out
// if the student has accidentally created a cycle by pointing a later part of the list back to an earlier part.
public static class ListNode {
private static final List<ListNode> ALL_NODES = new ArrayList<ListNode>();
public static void clearCycleData() {
for (ListNode node : ALL_NODES) {
node.visited = false;
node.cycle = false;
}
}
public int data; // data stored in this node
public ListNode next; // link to next node in the list
public boolean visited; // has this node been seen yet?
public boolean cycle; // is there a cycle at this node?
// post: constructs a node with data 0 and null link
public ListNode() {
this(0, null);
}
// post: constructs a node with given data and null link
public ListNode(int data) {
this(data, null);
}
// post: constructs a node with given data and given link
public ListNode(int data, ListNode next) {
ALL_NODES.add(this);
this.data = data;
this.next = next;
this.visited = false;
this.cycle = false;
}
public ListNode __gotoNext() {
return __gotoNext(true);
}
public ListNode __gotoNext(boolean checkForCycle) {
if (checkForCycle) {
visited = true;
if (next != null) {
if (next.visited) {
// throw new IllegalStateException("cycle detected in list");
next.cycle = true;
}
next.visited = true;
}
}
return next;
}
}
// YOUR CODE GOES HERE
}
My work so far is this:
public int deleteBack(){
if(front==null){
throw new NoSuchElementException();
}else{
ListNode current = front;
while(current!=null){
current = current.next;
}
int i = current.data;
current = null;
return i;
}
}
Don't you want to iterate until the current.next is != null?
What you have now passes the entire list, and your last statements do nothing, since current is null already.
Think about the logic you have here
while(current!=null){
current = current.next;
}
When that loop exits, current == null, and then you try to access current's data. Does this point you in the right direction?
// This is the quick and dirty
//By Shewan
public int deleteBack(){
if(size()== 0){ throw new NoSuchElementException(); }
if(front==null){ throw new NoSuchElementException();
}else{
if(front.next == null){
int i = front.data;
front = null;
return i;
}
ListNode current = front.next;
ListNode prev= front;
while(current.next!=null){
prev = current;
current = current.next;
}
int i = current.data;
prev.next = null;
return i;
}
}

Categories