I am making a singly linked list where I need to put a delete method but getting error any help?
public void remove(int index) {
getNode(index - 1).Next = getNode(index + 1);
}
Many possible errors can happen here. For one, I definitively would put more verification before making any changes as if
Are you on the first element (Then the header would be then 2nd element);
Are you on the last element (then is getNode(index+1) returning correctly NULL or throwing an exception)?
Like Apokai rightly noted you need to take extreme care while deleting.
Here are three methods for deleting use whichever serves the purpose:
//Method to delete the first/head element
public void deleteAtFirst() {
if (head == null) {//If list is empty
System.out.println("Linked List EMPTY!!");
} else {//else if it is not empty
head = head.next;//assigning head the address of the next node
}
}
//Method to delete the last element
public void deleteAtLast() {
if (head == null) {//If list is empty
System.out.println("Linked List EMPTY!!");
} else if (head.next == null) {//else if it has only 2 elements
head = null;
} else {//else if it is not empty and has more than 2 elements
Node tmpNode = head;//taking a temporary node and initialising it with the first/head node
while (tmpNode.next.next != null) {//looping it till the 'second last' element is reached
tmpNode = tmpNode.next;
}
tmpNode.next = null;//assigning the next address of the second last node as null thus making it the last node
}
}
//Method to delete an element at a given position
//The first element is situated at 'Position:[0]'
public void deleteAtPosition(int pos) {
int size = getSize();//Getting the size of the linked list through a pre-defined method
if (head == null || pos > size - 1) {//if the position is beyond the scope of current list or the list is empty
System.out.println("Position: " + pos + "does not exist");
} else {
Node prevNode = null;
Node currNode = head;
if (pos == size - 1) {//if position is equal to size-1 then essentially the last element is to be deleted
deleteAtLast();
} else if (pos == 0) {//if position given is '0' then we need to delete the first element
deleteAtFirst();
} else {//else if it is any other valid position
for (int i = 0; i < pos; i++) {//looping till the desired position
prevNode = currNode;//the node just before the required position will be assigned here
currNode = currNode.next;//the current node
}
prevNode.next = currNode.next;//assigning the next address of previous node to the next of current node thus removing the current node from the list
}
}
}
Take care that if you use the last one then the above two methods are present in your code. Also it uses another method getSize() :
//Method to get the size of the list
public int getSize() {//return type is integer as we are returning 'int size'
if (head == null) {//if the list is empty
return 0;
}
int size = 1;//initialising size by one
Node tmpNode = head;//taking a temporary node and initialising it with the first/head node
while (tmpNode.next != null) {//looping till the end of the list
tmpNode = tmpNode.next;//incrementing node to the next node 'after every iteration' of the loop
size++;//incrementing the size
}
return size;//returning size
}
Related
public class linkedList {
Node head;
class Node {
int data;
Node next;
Node(int d){
data = d;
}
}
public void insertAfter(Node prev_node, int new_data){
if (prev_node == null){
System.out.print("The given previous node cannot be null");
return;
}
Node new_node = new Node(new_data);
new_node.next = prev_node.next;
prev_node.next = new_node;
}
}
For a given linked list: 11,73,80,41,22, if I'd want to insert a number (eg. 0) after 73, I can pass it as insertAfter(llist.head.next,0).
But that is as far as I can reach to name a prev_node. What goes in as argument if I wanted to enter the 0 after the third,fourth...etc position. What will the argument be then ?
PS : Forgive me if the title is misleading or confusing, I wasn't able to put the query in right words for the title.
If I understand your question right, you want to know what should be passed for the argument when you want to insert data at different positions. With only insertAfter method provided you need to traverse through the linked list manually. In the example given by you it goes as below:
Insert after 11 -> insertAfter(llist.head, 0)
Insert after 73 -> insertAfter(llist.head.next, 0)
Insert after 80 -> insertAfter(llist.head.next.next, 0)
Insert after 41 -> insertAfter(llist.head.next.next.next, 0)
Insert after 22 -> insertAfter(llist.head.next.next.next.next, 0)
But this is not a correct approach. You need to provide traversal mechanisms as well as other methods which can add the value at the head, at the end of the list, at a given position etc.
You need a method that starts from the head of the linked list, traverses to the desired position, and returns that Node. You can then use that Node as an argument to your insertAfter() method.
public Node getNodeAtPosition(Node head, int position){
if (head == null || position < 0)
throw new IllegalArgumentException("head == null or position < 0");
Node helper = head;
while (position != 0) {
if (helper == null)
throw new IllegalArgumentException("position > length of list");
helper = helper.next;
position--;
}
return helper;
}
as the title says, i want to compare 2 linked Lists ( Done and working ) and i want to delete Nodes with same values ONLY IN LIST 2 .. i wrote a code and tried it out, it works in specific cases but i can't seem to understand what's going on with it ( giving wrong outputs ). the idea i used is sticking a LinkedList at a node, comparing it with all the nodes in the other List then delete whenever it finds they are equal.
Here is the delete head code :
public void deleteHead() {
if (head != null) {
head = head.getNext();
}
}
and here is the CompareTo Code :
public int compareTo(NodeData nd) {
if (num == nd.getNum()) {
return 0;
}
if (num != nd.getNum()) {
return -1;
}
return 1;
}
And this is the Delete method
public void delete(LinkedList LL) {
Node curr = head;
Node curr2 = LL.head;
while (curr2 != null) { //To traverse LL when list1 is done traversing
while (curr != null) { //traverse list1 while checking for common Nodes to delete
if (curr2.getData().compareTo(curr.getData()) == 0) { //compare data in the Nodes
System.out.println(curr2.getData().getNum() + " FOUND, WILL BE DELETED");
deleteHead(); //delete the current node of list1
curr = curr.getNext();
break;
}
else if (curr2.getData().compareTo(curr.getData()) == -1 ){
System.out.println(curr2.getData().getNum() + " Doesn't Match");}
curr = curr.getNext(); //next node in list1
}
curr2 = curr2.getNext(); //next node in LL
}
}
i tried with a simple output :
Output
If the data of two nodes equals you're deleting the head of one of the lists instead of the current node.
Second, you should compare each element of the first with each element of the second list, the inner while loop will iterate and consume the second list, and when it's called again - there'll be nothing to iterate, so you should probably change:
while (curr2 != null) { //To traverse LL when list1 is done traversing
while (curr != null) { //traverse list1 while checking for common Nodes to delete
to:
while (curr2 != null) {
Node curr = head; // <-- pay attention here, every loop you need to start from the beginning!
while (curr != null) {
if ... {
delete(curr); // TODO: need to implement this method in your LinkedList class
else {
...
I have a question, I've looked around on the internet but couldn't find an example. But making a String trim() method in java (remove lead/trailing whitespace), I know the basic code for this is:
public LString trim(){
int i = this.size;
int j = 0;
int k = this.offset;
char[] arrayOfChar = this.data;
while ((j < i) && (arrayOfChar[(k + j)] <= ' '))
++j;
while ((j < i) && (arrayOfChar[(k + i - 1)] <= ' '))
--i;
return (((j > 0) || (i < this.size)) ? substring(j, i) : this);
}
But, how would you write this same method, but applied to a linked list? More specifically, a linked list that uses a Node class.
Here is what I did....correct me if this is wrong...I'll include relevant class information that pertains to the question.
public class LString{
private Node front = null; //first val in list
private Node back; //last val in list
private int size = 0;
private int i;
private int offset;
public LString(){
//construct empty list
Node LString = new Node();
front = null;
}
.......//skip down some methods to this one
//returns new lstring that is slice of lstring
//contains an endIndex as well
public LString substring(int beginIndex, int endIndex){
Node current = this.front;
int size = 0;
while(current != null && size < beginIndex){
size++;
current = current.getNext();
}
front = new Node();
front.setData(current.getData());
Node ocurrent = front;
while(current != null && size < endIndex){
current = current.getNext();
Node curr2 = new Node();
curr2.setData(current.getData());
ocurrent.setNext(curr2);
ocurrent = curr2;
size++;
}
ocurrent.setNext(null); //set next val to null to term string
return this;
}
public LString trim(){
String lstr;
int i = this.size;
int m = this.offset;
int k = charAt(m);
Node current = front;
while(current != null){
current = current.getNext();
if(current.data > '\u0020'){
return this;
} else if(current.data < '\u0020'){
LString lstring = new LString(); //this worked!?
return lstring;
}
}
return this.substring(k, m+1);
}
...............................................................
//My Node class:
public class Node{
public char data;
public Node next;
//constructors from page 956
public Node()
{
this('\0',null); //'\0' is null char for java
}
public Node(char initialData, Node initialNext)
{
data = initialData;
next = initialNext;
}
}
(If you are unfamiliar with the node class, it basically just creates a singly linked node to use as your links between data in your linked list class)
I've never seen an example or anything, so I thought I'd ask the community.
Assuming that
by trimming the list you want to remove leading and trailing elements that are null
and under "linked list that uses a Node class" you mean java.util.LinkedList
You should keep in mind that in java internal implementation of LinkedList is not exposed (note: java.util.LinkedList.Node has private access modifier), all modifications are performed through methods of iterator and LinkedList itself.
Implementation would be:
public static void trim (LinkedList list){
if (list == null || list.size() == 0) return;
Object element = null;
ListIterator i = list.listIterator();
while (i.hasNext() && element == null) {
element = i.next();
if (element == null) {
i.remove();
}
}
element = null;
i = list.listIterator(list.size());
while (i.hasPrevious() && element == null) {
element = i.previous();
if (element == null) {
i.remove();
}
}
}
However if you are reimplementing mutable strings via linked list as an exercise
(if not as an exercise then stop right there and use StringBuilder or StringBuffer), then, assuming that you implement it with doubly linked list, it will go like this:
EDIT: my bad, you can iterate to the first non-empty element and set reference directly to it, updated algorithm
Fetch first element
While fetched element is empty fetch next
Set head reference to the last fetched element, set last fetched element's prev reference to null
Fetch last element
While fetched element is empty fetch previous
Set tail reference to the last fetched element, set last fetched element's next reference to null
UPDATE With code you provided try something like this (since you are using singly-linked list, it is slightly different then the one described above):
public void trim(){
//early out if empty
if (front == null || back==null) return;
Node current = front;
//looking for the first non-empty element
while(current != null && current.data<'\u0020' ){
current = current.next;
}
//left trim
this.front = current;
//looking for last non-empty element
while (current!=null&¤t.next!=null&¤t.next.data>'\u0020'){
current = current.next;
}
//right trim
this.back = current;
if (current!=null){
current.next = null;
}
}
Assuming you just want to trim each String in a LinkedList, why not just iterate over each item?
LinkedList<String> myNodes = new LinkedList<String>();
myNodes.add('This is a node ');
myNodes.add(' another node '));
for (String s : myNodes){
s.trim();
}
public void deleteItem(int target)
{
int index = 0;
CarNode item = head;
while(item != null)
{
CarNode next = (item.node).node;
CarNode previous = item;
if (index == target)
{
previous.setNode(next);
}
item = element.node
index++;
}
}
Yeah, I don't know if I understood well, but I got told that you can use reference and don't have to directly refer to an object of the linked list in order to perform changes on the linked list.
A node contains the Car object and the node of another element of the LinkedList, right, so the reference is basically a clone that points to the same object as the original, but how come that the original is ignored and the reference takes precedence over the original when we modify the node of the reference? Sorry, it didn't make any sense to me and I've been scratching my head for hours over this.
The code should look like this:
public void deleteItem(int target)
{
int index = 0;
CarNode item = head;
CarNode prev = null;
while(item != null)
{
if (index == target) {
if (prev == null) {
head = item.getNode();
return; // We've removed the target.
} else {
prev.setNode(item.getNode());
return; // We've removed the target.
}
}
prev = item;
item = item.getNode();
index++;
}
}
So let's break this down:
int index = 0;
CarNode item = head;
CarNode prev = null;
We need two variables: one to store the element we're looking at, the other to store the previous element (which we will use to reconnect the list once we remove an element). To start, our current is the head, and our previous doesn't exist. index will let us know when we reach the target.
while(item != null)
We want to iterate until we've hit the end of the list, marked by a null node.
if (index == target) {
if (prev == null) {
head = item.getNode();
return; // We've removed the target.
} else {
prev.setNode(item.getNode());
return; // We've removed the target.
}
}
If we've found the target, we remove it. If previous is null, then the target was the head, so we move the head to the 2nd element. Otherwise, we make the previous node's reference to be the current node's reference, which cuts the current node out of the list. Once we remove the target, we are done, so we return.
prev = item;
item = item.getNode();
index++;
Update the previous and current nodes. Both are moved forward one node. Index is incremented.
How about an illustrated example:
Take a list of size 3. It looks like this:
We now call list.deleteItem(1); This instantiates a prev and a next node. next points to the first node, and prev is null.
Our target is 1, so we move to the next node. Now prev points to what next used to point to, and next points to the 2nd object in the list (the one we want to remove).
We remove it by setting the prev node's reference to be the next node's reference.
When we return from the method, java garbage collection does its job, and we're left with:
Tada! Node removed from the list!
public void deleteItem(int target)
{
int index = 0;
CarNode item = head;
CarNode next = null;
CarNode previous = null;
// stop when the linked-list ends
while(item != null)
{
// the tail has no next node
if (item.node != null)
next = item.node.node;
else
next = null;
// if targetIndex exist, remove it
// "logically" from the linekd-list
if (index == target)
{
previous.setNode(next);
break;
}
// today is tomorrow's yesterday
previous = item;
item = item.node;
index++;
}
}
I previously needed help debugging my deleteNode method. It works now (updated version posted below) but I want it to provide for the case when it has to delete the head node. At the moment, it returns a NullPointerException where I've inserted * in deleteNode. I don't know how any of my variables can be null at that point, seeing as my while loop requires both position and head to not be null in the first place.
public class LinkedList
{
private class Node
{
int item;
Node link;
#SuppressWarnings("unused")
public Node()
{
item = Integer.MIN_VALUE;
link = null;
}
public Node(int x, Node p)
{
item = x;
link = p;
}
}
private Node head;
public LinkedList()
{
head = null;
}
public boolean deleteNode (int target)
{
Node position = head;
boolean isGone = false;
while(position != null && head != null)
{
if(position.link == head && position.link.item == target)
{
head = head.link;
isGone = true;
return isGone;
}
*** else if(position.link.item == target && position.link != head)
{
position.link = position.link.link;
isGone = true;
return isGone;
}
position = position.link;
}
return isGone;
}
public void printList()
{
System.out.println("Your list is: ");
Node position = head;
while(position != null)
{
System.out.println(position.item + " ");
position = position.link;
}
System.out.println();
}
}
LinkedList.deleteNode(int) never modifies any node's link, so it doesn't remove any element from the list.
Suppose that nodeA.link == nodeB, and nodeB.item == target. Then you need to set nodeA.link = nodeB.link, so that nothing is pointing to nodeB anymore.
Here is a list of the problems I see:
The enumerator you actually want to use, position, is never updated. The enumerator that is updated, counter is not needed.
You are never actually removing the node. In order to remove the node, you need to set the previous node's link to the matching node's link, thus removing it out of the chain.
You aren't dealing with special cases. What happens if the list passed is null? What happens if the matching node is the first node? The last node?
You should be returning the head of the linked list from the calling function. This is required for when removing the head node of the linked list.
Since this is a homework question, try to work it out for yourself but hopefully those points will help.
Look at your deleteNode() while loop code.
while(position != null && counter != null)
{
itemAtPosition = position.item;
if(itemAtPosition == target)
{
position = position.link;
isGone = true;
}
counter = counter.link;
}
you update counter, but never refer to it. position never changes, so the
if(itemAtPosition == target)
line never returns true. I suspect somewhere you need to check on counter.item!
First, you didn't write code for the case where the target item is located at the beginning, in which the field head should be updated accordingly. Second, the compared item is never updated during traversing the list.