Remove item from LinkedList - java

Small problem i am having with a program here. I am trying to create a program that adds Words to Linked Lists within a Array depending on their hashCode, determined by my hashFunction. If they have the same value for their hashCode they get added into a Linked List. I have a small count method that counts how many times a word is in the List. It works by computing the value for their hashFunction. It then goes to that value in the array, and iterates through the LinkedList until it reaches a Null value. It has a count variable which is incremented each time it finds the word in the list. This is my code:
public class test{
public static class Node<T>{
public T data;
public Node<T> next;
public Node(){
}
public Node(T data, Node<T> next)
{
this.data = data;
this.next = next;
}
}
static Node[] array = new Node[512];
public static void add(String word){
int position = hashFunction(word);
if(array[position] == null){
array[position] = new Node(word, null);
}else{
Node newHead = new Node(word, array[position]);
array[position] = newHead;
}
}
public static void remove(String word){
int remove = hashFunction(word);
Node head = array[remove];
if(head.data == word){
head = head.next;
System.out.println("Found");
}else if(head.data != word){
for(; array[remove] != null; array[remove] = array[remove].next){
if(array[remove].data == word){
array[remove] = array[remove].next;
}
}
System.out.println("Yusuf");
}
}
public static int count(String word){
int number = 0;
int position = hashFunction(word);
for(; array[position] != null; array[position] = array[position].next){
if(array[position].data == word){
number++;
}
}
System.out.println(number);
return number;
}
public static int hashFunction(String a){
int sum = 1;
for(int i = 0; i<a.length(); i++){
char b = a.charAt(i);
int value = (int) b;
sum *= value;
}
return sum % array.length;
}
public static void addthings(String word, int n){
for(int i = 0; i<n; i++){
add(word);
}
}
public static void main(String[] args) {
addthings("abc", 500000);
count("abc");
count("abc");
count("abc");
count("abc");
}
}
My issue is the first time I add values in it and check how many times it occurs it works fine, but any more calls to the Count method after that returns 0 for some reason.
I have another issue too which is my remove method isn't removing the items from the Linked List I want it too. The code iterates through the List, and when it finds the item which is meant to be removed, it removes the pointer from there and points it to the next value. This isn't working however.
Can someone show me how to fix these two issues please?
Thanks.

In your function if you write something Node head it means you are creating some local instance for a Node. If you set head = head.next this will simply change the state of your local instance variable not the state of your array.
You are checking if the first node contains the data which you are looking and trying to remove it then you have to remove it from your source Array(Array in which your references reside).So you can write something like this:
if(head.data == word)
array[remove] = head.next;
This was an example. The point is that you are not chaning things in your array but in your local variable.
public static void remove(String word){
int remove = hashFunction(word);
Node head = array[remove];
if(head.data == word){
head = head.next;
System.out.println("Found");
}else if(head.data != word){
for(; array[remove] != null; array[remove] = array[remove].next){
if(array[remove].data == word){
array[remove] = array[remove].next;
}
}
System.out.println("Yusuf");
}
}
A second mistake is in second clause where you just set array[remove] = array[remove].next;
It will break your linkedlist into two different linkedlist. Suppose you have 4 elements in linkedlist A,B,C,D and you remove B and there were pointers like this A->B->C->D then you are adding no pointers from A -> C. Here you break your linkedlist.
You can use while loop that will work easily.

Related

Print out and sort values inside LinkedList

I wrote a recursive backtracking algorithm for the so-called "Coin Change Problem". I store the coin values (int) in a self-written LinkedList ("ll") and each of those LinkedLists is stored inside one master LinkedList ("ll_total"). Now, when I try to print out the LinkedLists inside the master LinkedList, all I get is "LinkedList#1e88b3c". Can somebody tell me how to modify the code, in order to print out the coin values properly?
I would also like the algorithm to chose the LinkedList with the least values stored inside, as it would represent the optimal coin combination for the "coin change problem".
import java.util.Scanner;
public class CoinChange_Backtracking {
static int[] coins = {3, 2, 1};
static int index_coins = 0;
static int counter = 0;
static LinkedList ll = new LinkedList();
static LinkedList ll_total = new LinkedList();
public static void main(String[] args) {
Scanner myInput = new Scanner(System.in);
int amount;
System.out.println("Put in the amount of money: ");
amount = myInput.nextInt();
if (amount < 101) {
//Start recursion and display result.
recursiveFunction(coins, amount, index_coins, ll);
ll_total.show_ll();
} else {
System.out.println("The value must be less than 100!");
}
}
public static LinkedList recursiveFunction(int[] coins, int amount, int index_coins, LinkedList ll) {
//The current coin is being omitted. (If index_coins + 1 is still within range.)
if ((index_coins + 1) < coins.length) {
ll = recursiveFunction(coins, amount, index_coins + 1, ll);
ll_total.insert_ll(ll);
for (int i = 0; i < counter; i++) {
ll.deleteAt(0);
}
counter = 0;
}
//The current coin is not being omitted. (If there is still some change left and value of change isn't lower than value of current coin.)
if (amount != 0) {
if (amount >= coins[index_coins]) {
ll.insert(coins[index_coins]);
counter++;
ll = recursiveFunction(coins, amount - coins[index_coins], index_coins, ll);
}
}
return ll;
}
}
public class LinkedList {
Node head;
public void insert(int data) {
Node node = new Node();
node.data = data;
node.next = null;
if (head == null) {
head = node;
} else {
Node n = head;
while(n.next != null) {
n = n.next;
}
n.next = node;
}
}
public void insert_ll(LinkedList ll) {
Node node = new Node();
node.ll = ll;
node.next = null;
if (head == null) {
head = node;
} else {
Node n = head;
while(n.next != null) {
n = n.next;
}
n.next = node;
}
}
public void deleteAt(int index) {
if(index == 0) {
head = head.next;
} else {
Node n = head;
Node n1 = null;
for (int i = 0; i < index - 1; i++) {
n = n.next;
}
n1 = n.next;
n.next = n1.next;
n1 = null;
}
}
public void show() {
Node node = head;
while(node.next != null) {
System.out.println(node.data);
node = node.next;
}
System.out.println(node.data);
}
public void show_ll() {
Node node = head;
while(node.next != null) {
System.out.println(node.ll);
node = node.next;
}
System.out.println(node.ll);
}
//A toString method I tried to implement. Causes an array error.
/*
public String toString() {
Node n = head.next;
String temp = "";
while (n != null) {
temp = temp + n.data + " ";
n = n.next;
}
return temp;
}
*/
}
public class Node {
int data;
LinkedList ll;
Node next;
}
To answer your question. You are printing the linked list object, see here System.out.println(node.ll);
There are several ways to do it right. One approach is to question why you use Node and LinkedList the way you do ? A node can have a linked list and a linked list can have a node, I believe this is not really what you wanted. Maybe you can make it work, but from a design point of view in my experience it is not good. I find it confusing and it's a great source of bugs.
I try to list some points that caught my eye (or that my IDE had caught for my eyes).
You are not closing the Scanner object. Just close it at the end of the program or use the try-with-resources.
As mentioned before you have linked list that has a node and a node that has a linked list. You are not using that correctly in your program. I recommend to review that approach. It is error prone.
Also simply use the LinkedList of the Java library unless you have a good reason not to. It works fine and offers all you need.
You use many static, global (within the scope of the package) variables. In this case I think you can avoid that. coins does not need to be given as a parameter every time. It should be an immutable object. It is not supposed to change.
...
And I am not sure if it is a backtracking algorithm. It is certainly tree recursive. This just as a side note.
I'd like to propose a solution that looks similar to yours. I'd probably do it differently my way, but then it probably takes time to understand it. I try to adopt your style, which I hope helps. I simplified the program.
In order to print the result, simply write a helper function.
The linked list is an object. You have to make a copy of the list every time you call the recursion in order to work on a dedicated object. Otherwise you modify the same object while recursing different paths.
You can simply use a list of lists. A global list of lists (within package scope), and a list of which you make a copy every time you recurse. When you reach a good base case you add it to the global list. Otherwise just ignore.
import java.util.LinkedList;
import java.util.Scanner;
public class CoinChangeBacktracking {
static final int[] COINS = {3, 2, 1};
static final LinkedList<LinkedList<Integer>> changes = new LinkedList<>();
public static void main(String[] args) {
Scanner myInput = new Scanner(System.in);
int amount;
System.out.println("Put in the amount of money: ");
amount = myInput.nextInt();
if (amount < 101) {
// Start recursion and display result.
recursiveFunction(amount, 0, new LinkedList<>());
print(changes);
} else {
System.out.println("The value must be less than 100!");
}
myInput.close();
}
static void recursiveFunction(int amount, int index,
LinkedList<Integer> list) {
// exact change, so add it to the solution
if (amount == 0) {
changes.add(list);
return;
}
// no exact change possible
if (amount < 0 || index >= COINS.length) {
return;
}
// explore change of amount without current coin
recursiveFunction(amount, index + 1, new LinkedList<>(list));
// consider current coin for change and keep exploring
list.add(COINS[index]);
recursiveFunction(amount - COINS[index], index, new LinkedList<>(list));
}
static void print(LinkedList<LinkedList<Integer>> ll) {
for (LinkedList<Integer> list : ll) {
for (Integer n : list) {
System.out.print(n + ", ");
}
System.out.println();
}
}
}

Linked List in my Array not working

I am trying to create a program to store words in a Array. I have a hashFunction which computes a Integer value. This value is used to put the Word in a Node if that position in the array is null. If there is already a Cell there, it should create a new Cell with the word as its data type, and it should then point to the old Cell with all the other data. However this dosen't seem to be working - I have added a few words and although it adds the first word to the Cell the other words aren't being added. I'm not sure why this is happening - can someone show my why?
public class test2{
public static class Node<T>{
public T data;
public Node<T> next;
public Node(T data, Node<T> next)
{
this.data = data;
this.next = next;
}
}
static Node[] array = new Node[10];
public static void add(String word){
int position = hashFunction(word);
if(array[position] == null){
array[position] = new Node(word, null);
}else{
new Node(word, array[position]);
}
}
public static int hashFunction(String a){
int sum = 1;
for(int i = 0; i<a.length(); i++){
char b = a.charAt(i);
int value = (int) b;
sum *= value;
}
return sum % array.length;
}
public static void main(String[] args) {
add("abc");
add("acb");
add("bca");
add("bac");
add("cba");
System.out.println(array[4].next);
}
}
Instead of
new Node(word, array[position])
You should do the following:
array[position] = new Node(word, array[position]);
With the original line of code you are correctly creating an new instance of Node to which you assigned the current array[position] as its next value.
But array[position] is still the same, you need to change it to the newly created instance of Node.
You're adding the word as a new node in your linked list, but you're never storing a reference to the new node. When you add a node at the beginning of a linked list, you have to store the new node as the new head of the list.
In your case, you could accomplish that with the following:
public static void add(String word){
int position = hashFunction(word);
if(array[position] == null){
array[position] = new Node(word, null);
}else{
Node newHead = new Node(word, array[position]);
array[position] = newHead;
}
}
Now your linked list will have all of the words you're expecting. You could also iterate over the linked list in array[position] and add the new node at the end of the list if that's more appropriate for your use case.

How to build a linked list with a method that has two integer parameters and returns the reference to the first element of a list of nodes?

So I am having trouble trying to build a linked list from a method that has two integer parameters n and m. Parameter n is the length of nodes of the linked list, and m is the parameter that contains random integers from 0 to m-1 inside the list of nodes. I am required to build this linked list from a predefined Node class that cannot be changed, and to return the reference to the first element from the linked list. I don't know how to traverse the linked list in the while loop.
Node class
public class iNode{
public int item;
public iNode next;
public iNode(int i, iNode n){
item = i;
next = n;
}
public iNode(int i){
item = i;
next = null;
}
Build the linked list method
public static iNode list(int n, int m){
iNode first;
iNode newNode;
iNode last;
first = null;
while ( )
{
newNode = new iNode(m, first.next);
if (m > 0){
newNode.item = m-1;
}
newNode.next = null;
if (first == null)
{
first = newNode;
last = newNode;
}
else
{
last.next = newNode;
last = newNode;
}
}
return first;
}
You are overcomplicating it. Just go from the end of the list and add nodes with the link to the previous one. In the end just return the last created node. Also, you are not adding random int from the range 0..m-1. Here it is:
public static void main(String[] args) {
iNode res = list(5, 10);
while(res != null){
System.out.println(res.item);
res = res.next;
}
}
public static iNode list(int n, int m) {
iNode previous;
iNode current;
int i = 0;
previous = null;
while (i < n) {
current = new iNode(ThreadLocalRandom.current().nextInt(0, m), previous);
previous = current;
i++;
}
return previous;
}
Output:
2
5
7
8
9
P.S. Please follow java code convention. Class names should start with capital letter - iNode

Homework - Java - Selection Sort on my created double-linked list

My assigment is to create my own linked list class (I can't use Java's LinkedList class) and implement a selection sort on it by swapping pointers rather than data.
I've created a double-linked MyLinkedList class, but I'm having trouble with the sort method. I've tried a number of things but nothing has worked - not even anything that would make sense to post here for correction. (I do know that I need to use at least one temp Node.) It has to be a selection sort.
I'm not looking for someone to code it for me, necessarily; I'm hoping someone can help me with an algorithm that I can then turn into code myself. Any help is appreciated greatly.
Here's how I've implemented the MyLinkedList class and the associated Node class:
public class MyLinkedList
{
private Node head;
private int count;
public MyLinkedList()
{
head = new Node(null);
count = 0;
}
public void add(String line)
{
Node temp = new Node(line);
Node current = head;
while (current.getNext() != null)
{
current = current.getNext();
}
temp.setLine (line); // not sure this is how to do it
current.setNext(temp);
temp.setPrev(current);
count++;
}
public void displayList()
{
Node current = head;
for (int i = 0; i < count; i++)
{
current = current.getNext();
System.out.println(current.getLine());
}
}
public void sortList()
{
Node start = head;
Node index = start;
Node min = start;
Node temp1, temp2;
while (start.getNext() != null)
{
index = index.getNext();
if (index.getLine().compareTo(min.getLine()) < 0)
{
min = index;
}
//swap - HELP, PLEASE :-)
{
// Algorithm???
}
}
}
public int size()
{
return count;
}
private class Node
{
String textLine;
Node next;
Node prev;
public Node()
{
textLine = null;
next = null;
prev = null;
}
public Node (String line)
{
textLine = (line);
next = null;
prev = null;
}
public Node (String line, Node node1, Node node2)
{
textLine = line;
prev = node1;
next = node2;
}
public String getLine()
{
return textLine;
}
public Node getNext()
{
return next;
}
public Node getPrev()
{
return prev;
}
public void setLine(String line)
{
textLine = line;
}
public void setNext(Node nextNode)
{
next = nextNode;
}
public void setPrev(Node prevNode)
{
prev = prevNode;
}
}
}
It may get confusing if an empty MyLinked List has a node in it even if it's just one with null prev, next and data, so you need to be careful of that MyLinkedList constructor - it would probably be much easier if it read simply head = null;.
Also it would be useful if a MyLinked List had a tail node as well to save you following the chain to the end to find where add should put a new Node.
After that, I think the problem is that you haven't noticed you need two loops: one to work your way through the list to keep track of where the unsorted nodes start, and one to find the smallest node from thereon. You also need to write a swap method for Node so that you can write something like this untested pseudocode that just happens to look a lot like Java
for (index = head; index != null; index = index.getNext()) {
min = index;
for (test = min.getNext(); test != null; test = test.getNext) {
if (test.getLine().compareTo(min.getLine()) < 0)
min = test;
}
if (min != index) {
swap(index, min);
index = min;
}
}
and swap would look roughly like
public void swap(Node other)
{
Node temp;
temp = next;
next = other.getNext();
other.setNext(temp);
temp = prev;
prev = other.getPrev();
other.setPrev(temp);
other.getNext().setPrev(this);
other.getPrev().setNext(this);
this.getNext().setPrev(other);
this.getPrev().setNext(other);
}
Note again this is completely untested and hasn't even seen a compiler.
Make sure to think about special cases like when the list is empty or has only one element in it, and when there is only one node left unsorted in the list.
I couldn't leave this without pointing out that swap is actually a lot more complex than that. I've added a few lines to correct the pointers in the nodes before and after the nodes to be swapped. You also need to consider:
Whether either of the nodes that are swapped are at the end of the list, in which case the head (and tail if you have one) of the list will need to be updated instead of the pointers in the adjacent nodes. That's fairly obvious.
Whether the nodes to be swapped are next to each other in the list, when if you apply the normal algorithm you get nodes pointing to themselves. That's less obvious.

Java Linked List Sorting

So the app reads from an external file a bunch of strings, each on a separate line.
For example:
and
cake
here
It is not arranged in any particular order. I need to read these letters and put them into linked list and finally sort them.
I need help on doing that:
Here is the current code:
import java.util.*;
import java.io.*;
public class LinkedList
{
static File dataInpt;
static Scanner inFile;
public static void main(String[] args) throws IOException
{
dataInpt=new File("C:\\lldata.txt");
inFile=new Scanner(dataInpt);
Node first = insertInOrder();
printList(first);
}
public static Node getNode(Object element)
{
Node temp=new Node();
temp.value=element;
temp.next=null;
return temp;
}
public static void printList(Node head)
{
Node ptr; //not pointing anywhere
for(ptr=head;ptr!=null;ptr=ptr.next)
System.out.println(ptr.value);
System.out.println();
}
public static Node insertInOrder()
{
Node first=getNode(inFile.next());
Node current=first,previous=null;
Node last=first;
int count=0;
while (inFile.hasNext())
{
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) < 0)
{
current.next=last;
last=current;
}
previous=current;
current=getNode(inFile.next());
}
return last;
}
}
But that gives an infinite loop with "Cat".
Here is the data file:
Lol
Cake
Gel
Hi
Gee
Age
Rage
Tim
Where
And
Kite
Jam
Nickel
Cat
Ran
Jug
Here
Okay, self-study. Split the reading and inserting. Though old and new code both have 14 lines of code,
it makes it more intelligable.
public static Node insertInOrder() {
Node first = null;
while (inFile.hasNext()) {
String value = inFile.next().toString();
first = insert(first, value);
}
return first;
}
/**
* Insert in a sub-list, yielding a changed sub-list.
* #param node the sub-list.
* #param value
* #return the new sub-list (the head node might have been changed).
*/
private static Node insert(Node node, String value) {
if (node == null) { // End of list
return getNode(value);
}
int comparison = node.value.compareTo(value);
if (comparison >= 0) { // Or > 0 for stable sort.
Node newNode = getNode(value); // Insert in front.
newNode.next = node;
return newNode;
}
node.next = insert(node.next, value); // Insert in the rest.
return node;
}
This uses recursion (nested "rerunning"), calling insert inside insert. This works like a loop, or work delegation to a clone, or like a mathematical inductive proof.
Iterative alternative
also simplified a bit.
private static void Node insert(Node list, String value) {
Node node = list;
Node previous = null;
for (;;) {
if (node == null || node.value.compareTo(value) >= 0) {
Node newNode = getNode(value);
newNode.next = node;
if (previous == null)
list = newNode;
else
previous.next = newNode;
break;
}
// Insert in the rest:
previous = node;
node = node.next;
}
return list;
}
public static Node insertInOrder()
{
Node first=getNode(inFile.next());
Node current=first,previous=null;
Node last=first;
int count=0;
while (inFile.hasNext())
{
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) < 0)
{
current.next=last;
last=current;
}
previous=current;
current=getNode(inFile.next());
}
return last;
}
First of all, you never do anything with the last line read from the file, so that's not ever inserted. You have to read the line and create the new Node before relinking next pointers.
Then, if last and previous refer to the same Node and the data of current is larger than that of previous,
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
You set last.next = last, breaking the list. From the code (in particular the absence of a sort(Node) function), it seems as though you want to sort the list as it is created. But you only ever compare each new Node with one other, so that doesn't maintain order.
For each new node, you have to find the node after which it has to be inserted, scanning from the front of the list, and modify current.next and the predecessor's next.
In relatively simple code like that in your question, a good exercise to understanding it is to work through a few interations of your loop, inspecting the values of all your local variable to see the effect of your code. You can even do it by hand if the code is simple. If it is too difficult to do by hand, your code is probably too complicated. If you can't follow it, how can you know if you are doing what you intend. For example, I could be wrong, but this appears the be the state at the top of each iteration of the loop. It starts falling apart on the third time through, and by the fourth you have a severe problem as your list becomes disjointed.
1)last = first = Lol, current = previous = null
Lol->null
2)last = first = previous = Lol, current = Cake
Lol->Lol
3)first = Lol, last = Cake, previous = Cake, current = Gel
Cake->Lol->Lol
4)first = Lol, last = Cake, previous = Cake, current = Hi
Cake->Gel, Lol->Lol
Quite honestly, if I were running the course, I would consider the correct answer to be:
List<String> list = new LinkedList<String>();
// read in lines and: list.add(word);
Collections.sort(list);
Ok, I don't remember exactly school theory about insertion sort, but here is somehow a mix of what I think it is and your code:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class LinkedList {
public static class Node {
public String value;
public Node next;
}
static File dataInpt;
static Scanner inFile;
public static void main(String[] args) throws IOException {
inFile = new Scanner("Lol\r\n" + "Cake\r\n" + "Gel\r\n" + "Hi\r\n" + "Gee\r\n" + "Age\r\n" + "Rage\r\n" + "Tim\r\n" + "Where\r\n"
+ "And\r\n" + "Kite\r\n" + "Jam\r\n" + "Nickel\r\n" + "Cat\r\n" + "Ran\r\n" + "Jug\r\n" + "Here");
Node first = insertInOrder();
printList(first);
}
public static Node getNode(String element) {
Node temp = new Node();
temp.value = element;
temp.next = null;
return temp;
}
public static void printList(Node head) {
Node ptr; // not pointing anywhere
for (ptr = head; ptr != null; ptr = ptr.next) {
System.out.println(ptr.value);
}
System.out.println();
}
public static Node insertInOrder() {
Node current = getNode(inFile.next());
Node first = current, last = current;
while (inFile.hasNext()) {
if (first != null && current.value.compareTo(first.value) < 0) {
current.next = first;
first = current;
} else if (last != null && current.value.compareTo(last.value) > 0) {
last.next = current;
last = current;
} else {
Node temp = first;
while (current.value.compareTo(temp.value) < 0) {
temp = temp.next;
}
current.next = temp.next;
temp.next = current;
}
current = getNode(inFile.next());
}
return first;
}
}
And it works like a charm. Of course this far from optimal, both in terms of performance and code reuse.

Categories

Resources