I am creating an implementation of a linked list and am having trouble with the add method. After testing it with several entries, my size() method always returns 1. what am i doing wrong.
public class Node {
public int data;
public Node next;
public Node(int data){
this.data = data;
}
}
public class LinkedList {
public Node first;
public Node last;
public LinkedList(){
first = null;
last = null;
}
public void add(int data){
Node newNode = new Node(data);
if(first == null){
first = newNode;
} else {
add(first, newNode);
}
}
public void add(Node currentNode, Node newNode){
if(currentNode.next != null){
add(currentNode.next, newNode);
}
currentNode.next = newNode;
}
public int size(){
if(first == null){
return 0;
}
else{
return size(first);
}
}
public int size(Node currentNode){
//Count Starts At One Because First = 1.
int count = 1;
if(currentNode == null){
return count;
}
else {
count++;
return size(currentNode.next);
}
}
}
You forgot the else in the 2-arg form of add. As it stands,
if(currentNode.next != null){
add(currentNode.next, newNode);
}
currentNode.next = newNode;
will always add the new node to first and to all the other nodes in the list. If currentNode.next = newNode appears in an else clause, it will be added correctly only to the end.
Additionally, your size method always returns 1 because the final branch always returns 1. To fix this, change
count++;
return size(currentNode.next);
to
return 1 + size(currentNode.next);
Also, replace return count; with return 1;.
Basically, your implementation is almost correct. size(Node) should return the size of the list starting with that node. If the node does not have a next, the size is 1. Otherwise, its the current node (1) + the size of the remaining tail.
You should make the 2-arg versions of add and the 1-arg version of size private since you don't want to expose the internals of your list to the public (in fact, the Node class should be a private class as well).
Additionally, you never use the last field of your class. You can either remove it, or use it to avoid the need for recursion completely in add. In the latter case, you will have to update it correctly with every new addition.
In place of return size(currentNode.next); try this return count + size(currentNode.next);
It will fix the count problem given that, the list is fine. But checking your code at a glance looks like the list addition code is also buggy.
Related
I am supposed to build a method that will remove the first instance of a given value in a singly-linked list. However, whenever I try to test this method it will get stuck and I have to force the code to terminate.
edit: following advice, I have made a modified version method Contains that now works well and eliminates pointless repetition of Contains. so happily now the code works as it should!
Here is my code for the method:
public boolean remove(Anything m) {
//INCOMPLETE
if (this.first==null) {
System.out.println("there are no values in the list");
return false;
}
boolean returnValue;
returnValue=false;
if (this.contains(m)==true) {
Node temp=first;
while(temp.next!=null) {
if (temp.next.data==m) {
temp=temp.next.next;
temp.next=null;
returnValue=true;
}
else
returnValue=false;
}
}
return returnValue;
}
Here is my code for testing the method:
list13.addFirst("node5"); list13.addFirst("node4"); list13.addFirst("node3"); list13.addFirst("node2"); list13.addFirst("node1");
System.out.println("5-element list: " + list13);
System.out.println("Testing remove...");
System.out.println(list13.remove("node3"));
and just in case, here is the prebuilt code my assignment came with, if needed:
public class CS2LinkedList<Anything>
{
// the Node class is a private inner class used (only) by the LinkedList class
private class Node
{
private Anything data;
private Node next;
public Node(Anything a, Node n)
{
data = a;
next = n;
}
}
private Node first;
private Node last;
public CS2LinkedList()
{
first = null;
}
public boolean isEmpty()
{
return (first == null);
}
public void addFirst(Anything d)
{
Node temp = first;
first = new Node(d,temp);
}
public void clear()
{
first = null;
}
public boolean contains(Anything value)
{
for (Node curr = first; curr != null; curr = curr.next)
{
if (value.equals(curr.data)) {
return true;
}
}
return false;
}
public String toString()
{
StringBuilder result = new StringBuilder(); //String result = "";
for (Node curr = first; curr != null; curr = curr.next)
result.append(curr.data + "->"); //result = result + curr.data + "->";
result.append("[null]");
return result.toString(); //return result + "[null]";
}
```
Some issues:
At a match, you are reassigning to temp the node that follows after the node to be deleted, and then you clear temp.next. That is breaking the list after the node to be deleted.
The while loop does not change the value of temp when the if condition is not true. So the loop can hang.
You can stop the search when you have identified the node to delete. By consequence you don't need the else inside the while loop.
while(temp.next!=null) {
if (temp.next.data==m) {
// skip the node by modifying `temp.next`:
temp.next = temp.next.next;
returnValue=true;
break; // we removed the targeted node, so get out
}
temp = temp.next; // must move to next node in the list
}
It is a pity that you first iterate the list with this.contains(m), only to iterate it again to find the same node again. I would just remove that if line, and execute the loop that follows any way: it will detect whether the list contains the value or not.
Be aware that your function has no provision for removing the first node of the list. It starts comparing after the first node. You may want to cover this boundary case.
As a homework assignment I'm suppose to return the position of the second to last occurrence of a letter--to know what letter to check it is passed as a Char type parameter. What I'm searching through is a self-coded linked list. It also has to be done recursively, which I've been struggling to fully understand. Here's what I've worked out so far.
Note: If a letter appears either 0 or 1 time, return -1.
E.g.
["ababcdefb"].positionOfSecondToLastOccurrence('b') == 3
static class Node {
public Node (char item, Node next) { this.item = item; this.next = next; }
public char item;
public Node next;
}
Node first;
public int positionOfSecondToLastOccurrence (char letter) {
if (first == null)
return -1;
return positionOfSecondToLastOccurrenceHelper(letter, first, 0);
}
private int positionOfSecondToLastOccurrenceHelper(char c, Node n, int pos) {
if (n.next == null)
return n.item;
return pos += compare(n.item, positionHelper(c, n.next, pos));
}
private int compare(char c, int p) {
int result = 0;
if (c == p)
return result += 1;
return 0;
}
I understand why this isn't working; I'm returning a result of 1 and then comparing it to n.item when going back to the previous function call, which will never be true. What I don't know is how to make this work. Any guidance would be awesome.
You are using a singly-linked list, which means you can only traverse it in one direction, namely forward, i.e. from the first node to the last node.
The algorithm is then to traverse the list from first node to last node and compare each node's item with the item you are searching for. Also you need two variables that will hold the index in the list of both the last (i.e. ultimate) and the second last (i.e. penultimate) occurrences of the item you are searching for. Both these variables should have initial values of -1 (minus one).
When you hit the first occurrence of the searched for item, update the ultimate index variable. When you hit the next occurrence, set the penultimate index to the ultimate index and then update the ultimate index.
Repeat for every subsequent occurrence of the searched for item, i.e. set the penultimate index to the ultimate index and then set the ultimate index to the index of the current node in the list. Hence if the searched for item occurs only once in the list, or does not occur at all, the penultimate index will be -1.
When writing a recursive method, the first thing you need is some condition that will terminate the recursion. If the condition is true, return an appropriate value. If the condition is false, change the method arguments and recall the same method with the modified arguments. The terminating condition in your case is a null node.
Since a list is not an array, you also need to track the index of the current node, so as to be able to return it from your recursive method.
Here is my implementation. I created a LinkList class which contains a list of your Node class. The LinkList class allows me to initially create a linked list. I also added method toString() to both Node and LinkList classes to help visualize what the list looks like. The main() method serves as a test of the recursive method. The first invocation of the recursive method uses the first node in the list, whose index is 0 (zero).
public class Penultim {
public static void main(String[] args) {
LinkList list = new LinkList();
list.append('a');
list.append('b');
list.append('a');
list.append('b');
list.append('c');
list.append('d');
list.append('e');
list.append('f');
list.append('b');
System.out.println(list);
System.out.println(list.getPenultimateOccurrenceIndex('b', list.getHead(), 0, -1, -1));
}
}
class Node {
private char item;
private Node next;
public Node(char item, Node next) {
this.item = item;
this.next = next;
}
public char getItem() {
return item;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public String toString() {
return item + "->";
}
}
class LinkList {
private Node head;
public void append(char item) {
if (head == null) {
head = new Node(item, null);
}
else if (head.getNext() == null) {
head.setNext(new Node(item, null));
}
else {
Node node = head.getNext();
while (node != null) {
if (node.getNext() == null) {
node.setNext(new Node(item, null));
break;
}
node = node.getNext();
}
}
}
public Node getHead() {
return head;
}
public int getPenultimateOccurrenceIndex(char item,
Node node,
int ndx,
int penultimate,
int ultimate) {
if (node == null) {
return penultimate;
}
else {
if (node.getItem() == item) {
if (ultimate >= 0) {
penultimate = ultimate;
}
ultimate = ndx;
}
return getPenultimateOccurrenceIndex(item,
node.getNext(),
ndx + 1,
penultimate,
ultimate);
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
Node node = head;
while (node != null) {
sb.append(node);
node = node.getNext();
}
return sb.toString();
}
}
The output when running the above code is
a->b->a->b->c->d->e->f->b->
3
I’d do this in smaller steps. I’d start by writing a positionOfLastOccurrence(char letter). Writing this as a recursive method should teach you some of the technique that you will also need for positionOfSecondToLastOccurrence().
Next much of the challenge is in a good design of the helper method or methods. I think that I’d write a positionOfLastOccurrenceBeforePosition(int pos, char letter) that should return the position of the last occurrence of letter strictly before position pos. So given your example list, ababcdefb, positionOfLastOccurrenceBeforePosition(0, 'b') would return -1, positionOfLastOccurrenceBeforePosition(2, 'b') would yield 1 and positionOfLastOccurrenceBeforePosition(100, 'b') would give 8. This method too should be recursive, I believe, since this will the one doing the actual work in the end.
Now finding the second last occurrence is a matter of first finding the last occurrence and then finding the last occurrence before that one.
I have written my own linked list and am reading integers from a file into the list and printing them out. However, only the head of my list is printing and nothing else. I've been staring at this code for so long I feel insane, can anyone help?
Method in a separate 'files' class that reads in a file of integers separated by whitespace. This method will take the next integer and add it to my linked list.
public void readValues() {
LinkedList list = new LinkedList();
while(scan.hasNextInt()) {
Integer someData = scan.nextInt();
list.addNode(someData);
}
list.printList();
}
This method is in my LinkedList class which takes the data sent from my readValues method in my files class.
public void addNode(Integer someData) {
myNode = new LinkedNode(someData,null);
//initialize node if this is first element
if (head == null) {
head = myNode;
size++;
}
else if (myNode.getNext() == null) {
myNode.setNext(myNode);
size ++;
}
else if (myNode.getNext() != null) {
while(myNode.getNext() != null) {
myNode = myNode.getNext();
}
myNode.setNext(myNode);
size++;
}
}
This method is also in my LinkedList class and successfully prints the head of my list which with my data is the number 40 followed by ---> and then nothing else. It should print ever other integer read in from my file.
public void printList() {
LinkedNode current = head;
if (head == null) {
System.out.print("list is empty");
return;
}
while(current != null) {
System.out.print(current.getElement());
System.out.print(" --> ");
current = current.getNext();
}
}
LinkedNode class:
public class LinkedNode {
Integer data;
LinkedNode next;
public LinkedNode(Integer someData, LinkedNode next) {
this.data = someData;
this.next = null;
}
public int getElement() {
return data;
}
public void setElement(Integer data) {
this.data = data;
}
public LinkedNode getNext() {
return next;
}
public void setNext(LinkedNode next) {
this.next = next;
}
public String toString() {
return data + "";
}
}
Your code has a small bug in the if else conditions in your addNode() method due to which your data is not getting added in the list.
Root Cause
When you add a new node to your list,
In the first iteration
The head is currently null and hence the first if conditions becomes true and your first node gets added (That's why you got the data 40).
In the Subsequent iteration(s)
your else if condition checks the myNode's next pointer which will always be null (as per the constructor) and thus it's next pointer points towards itself. The nodes created from here do not become the part of the list as the next pointer of head was never assigned to any of these and these nodes also point to themselves only.
Solution
I made a little modification in the if else conditions:
public void addNode(Integer someData) {
LinkedNode myNode = new LinkedNode(someData,null);
//initialize node if this is first element
if (head == null) {
head = myNode;
size++;
}
else if (head.getNext() == null) {
head.setNext(myNode);
size ++;
}
else if (head.getNext() != null) {
System.out.println("in second else if");
LinkedNode n = head;
while(n.getNext() != null) {
n = n.getNext();
}
n.setNext(myNode);
size++;
}
}
PS: Try debugging your code with dry run, it's a great mental exercise and helps in boosting the learning curve significantly too. All the best! :)
The problem is with your addNode() method. Inside the addNode() method you are first creating a new node named mynode. Now when the head is null it sets head to mynode, thats ok. But when the head is not null the mynode is not being added to the list. Thats why only the first element exist and other's are getting lost.
Hope this helps. Let me know if I can help with anything else. Happy coding!
So I am currently trying to create a circle linked list (double linked list with each value having a previous, and a next value not equal to null), and I am not sure if I am properly creating it. My goal is to be able to create a LinkedList of values, and then when I iterate through the list, hasNext() should always return true (no null values). I think there is something wrong with the way I am adding values, but I am not sure. Here is the code, with the CircularList class having an inner node class:
public class CircularList<E> {
//I decided to still have heads and tails, to link them together
private Node<E> first = null;
private Node<E> last = null;
private Node<E> temp;
private int size;
//inner node class
private static class Node<E>{ //In this case I am using String nodes
private E data; //matching the example in the book, this is the data of the node
private Node<E> next; //next value
private Node<E> prev; //previous value
//Node constructors, also since in this case this is a circular linked list there should be no null values for previous and next
private Node(E data, Node<E> next, Node<E> prev){
this.data = data;
this.next = next;
this.prev = prev;
}
}
//end of inner node class
public void addValue(E item){
Node<E> n = new Node<E>(item, first, last);
if(emptyList() == true){ //if the list is empty
//only one value in the list
first = n;
last = n;
}
else{ //if the list has at least one value already
temp = first;
first = n;
first.next = temp;
last.next = first;
}
size++;
}
public boolean emptyList(){
boolean result = false;
if(first == null && last == null){ //if there is no values at all
result = true;
}
return result;
}
}
Just did a quick scan but this is the bit where it goes wrong:
Node<E> n = new Node<E>(item, first, last);
if(emptyList() == true) {
//if the list is empty
//only one value in the list
first = n;
last = n;
}
The prev and next item inside node are still null here. You should set those too.
else {
//if the list has at least one value already
temp = first;
first = n;
first.next = temp;
last.next = first;
}
Additionally you're not updating prev here.
Also consider using a linked list internally as a backing data structure rather then your own node structure. Then you only have to create the circular iterator.
I am trying to delete a node in the middle of two other nodes in a singly linked list.
public void deleteAfter(Node del){
del.next=del.next.next;
}
where it deletes the the node that is after the specified node,del.
I get a null pointer exception .I think the problem is after deletion the link with other nodes is broken.How can I mend it .Here's my full code :
public class Node{
public Object item;
public Node next;
public Node(){
item=null;
next=null;
}
public Node(Object x){
item=x;
next=null;
}
public void insertAfter(Node after,Object x){
Node newNode=new Node(x);
newNode.next=after.next;
after.next=newNode;
}
public void deleteAfter(Node del){//Deletes the node that is after the specified node
del.next=del.next.next;
}
public static void main (String args[]){
Node front=new Node(),p=new Node(),q=new Node();
p.item="green";
q.item="red";
p.next=q;
front=p;
front.deleteAfter(p);
front.insertAfter(p,"black");
front.insertAfter(q,"blue");
front.insertAfter(q.next,"orange");
front.deleteAfter(q);
System.out.println(front.item);
System.out.println(front.next.item);
System.out.println(front.next.next.item);
System.out.println(front.next.next.next.item);
}
}
First your list should remember last element or head.
public class YourList{
Node heaed;
public YourList(){
head = null;
}
public void insert(Node node){
if(last == null){
head = node;
}
}
public void deleteAfter(Node del){
if(del.next == head)){
head = del;
}
if(del.next == null){
//do nothing because there is nothing to delete
}
else{
del.next=del.next.next;
}
}
}
At:
p.next=q;
front=p;
front.deleteAfter(p);
front.insertAfter(p,"black");
You have created a two node linked list starting at p, and pointed front to it, then you shrank it down to a one node linked list, and bumped it back to two, consisting of { "green", "black" }. q is a singleton list node which you later manipulate.
When you print starting from front, since it only has two nodes, trying to obtain the item of the third node, which doesn't exist, causes your exception.
Your question started out by asking if there was something wrong with your deleteAfter(), and there is in that it won't correctly handle any correct list of nodes, only a list that actually has something after it. Passing in an empty list or a list with only one node in it will result in an exception.
You can first find the middle node using two pointer approach and then delete the node.
public Node findMiddleNode(Node node){
Node runner = node;
while(node!=null){
node = node.next;
if(node != null){
node = node.next;
runner = runner.next;
}
}
return runner;
}
public static boolean deleteNode(Node node){
if(node==null || node.next==null) return false;
Node next = node.next;
node.data = next.data;
node.next = next.next;
return true;
}
Solution which first calculates the size of the list and deletes the n/2 element without using two pointers.
For example, if given linked list is 1->2->3->4->5 then linked list should be modified to 1->2->4->5. If there are even nodes, then there would be two middle nodes, the second middle element gets deleted. For example, if given linked list is 1->2->3->4->5->6 then it should be modified to 1->2->3->5->6.
public void deleteMiddle() {
if (head == null) {
System.out.println("List is emplty");
return;
} else if (head.next == null) {
head = null;
return;
} else {
int count = 0;
int nodeDeleteIndex = 0;
Node node = this.head;
Node temp = this.head;
// To calculate the list size
while (node != null) {
count++;
node = node.next;
}
// getting the n/2 index of the node which needs to be deleted
nodeDeleteIndex = (count / 2);
for (int i = 0; i < nodeDeleteIndex - 1; i++) {
temp = temp.next;
}
temp.next = temp.next.next;
}
}