I'm trying to write a code that handles a linked list. This linked list is somehow different because it's a key-value pair linked list (singly). The linked list should provide the user with basic functions, such as retrieving the size of linked list, checking for a key whether it's in the list or not, insertion, and deletion. It seems that all the functions are working properly except for the deletion. The code for the deletion method run correctly with no run time error, but it gives me results that's not what I wanted to have. Here is my code:
public class SequentialSearch<Key,Value> {
private int N; // number of key-value pairs
private Node head; // the linked list of key-value pairs
private Node tail;
// a helper linked list data type
private class Node {
private Key key;
private Value val;
private Node next;
public Node(Key key, Value val, Node next) {
this.key = key;
this.val = val;
this.next = next;
}
public void setNext(Node next) {
this.next = next;
}
}
public SequentialSearch() {
}
public int size() {
if (head == null)
return 0;
else {
Node x = head;
while (x.next != null) {
N++;
x = x.next;
}
}
return N;
}
public boolean isEmpty() {
return size() == 0;
}
public boolean contains(Key key) {
return get(key) != null;
}
public Value get(Key key) {
for (Node x = head; x != null; x = x.next) {
if (key.equals(x.key))
return x.val;
}
return null;
}
public void put(Key key, Value val) {
if (val == null) {
delete(key);
return;
}
for (Node x = first; x != null; x = x.next) {
if (key.equals(x.key)) {
x.val = val;
return;
}
}
first = new Node(key, val, first);
N++;
}
public boolean delete(Key key) {
Node curr = head;
Node prev = null;
boolean result = false;
if(isEmpty())
System.err.println("Error: The list is empty.");
while(curr != null) {
if(key.equals(curr.key)) {
if(curr.equals(head)) {
head = curr = null;
N--;
result = true;
return result;
} else {
prev.next = curr.next;
curr.setNext(null);
N--;
result = true;
return result;
}
} else {
prev = curr;
curr = curr.next;
}
}
return result;
}
}
I've written a main program to test for the add (put) and deletion, but it seems to be working for the insertion but not for the deletion. I think I might have a problem the deletion in case there is only one node in the list and the case of deleting a node from the middle of the list.
I'm also trying to modify the deletion method by writing a new method using the recursion, but I faced some errors -also logically. Here is the code of that function:
public void delete(Key key) {
first = delete(first, key);
}
private Node delete(Node x, Key key) {
if (x == null) return null;
if (key.equals(x.key)) {
N--;
return x.next;
}
x.next = delete(x.next, key);
return x;
}
Could you please tell me what did I do wrong?
head = curr = null;
This statement is a little confusing but I think it might be your problem for when deleting. If you're deleting a match that is at 'head', you just want to set head to 'curr.next'
What I think is going on:
delete(a)
a -> b -> c -> d
head = a
curr = a
curr.next = b
you set head to null, but head needs to point to the first item in the new list, which if you deleted 'a', would be 'b', or curr.next
Related
I am trying to return all node contents that match a given String input. What I am trying to do is essentially a very simple search engine, where the user is able to type in a String and the program returns all characteristically similar contents it can find in the linked list. The linked list itself is built from a file, formatted as
<<Game’s Name 0>>\t<<Game’s Console 0>>\n
<<Game’s Name 1>>\t<<Game’s Console 1>>\n
where the lines are delimited with a \n and the game and its corresponding console are delimited with a \t.
My current methodology follows searching the linked list with a while loop, assigning a temporary value to the head and reassigning it to it's link as it goes down the list. Once the loop finds contents within a node that matches the current input, it stops the loop and returns the data found in the node. I have yet to try if this could be done with a for loop, as the while loop more than likely would not know when to continue once it has found a match. I am also unsure if the while loop argument is the most efficient one to use, as my understanding of it is very minimal. I believe !temp.equals(query) is stating "temp does not equal query," but I have a feeling that this could be done in a more efficient manner.
This is what I have so far, I will provide the entire Generic linked list class for the sake of context, but the method I am questioning is the very last one, found at line 126.
My explicitly stated question is how can I search through a linked list's contents and return those contents through the console.
import java.io.FileNotFoundException;
import java.util.Scanner;
public class GenLL<T>
{
private class ListNode
{
T data;
ListNode link;
public ListNode(T aData, ListNode aLink)
{
data = aData;
link = aLink;
}
}
private ListNode head;
private ListNode current;
private ListNode previous;
private int size;
public GenLL()
{
head = current = previous = null;
this.size = 0;
}
public void add(T aData)
{
ListNode newNode = new ListNode(aData, null);
if (head == null)
{
head = current = newNode;
this.size = 1;
return;
}
ListNode temp = head;
while (temp.link != null)
{
temp = temp.link;
}
temp.link = newNode;
this.size++;
}
public void print()
{
ListNode temp = head;
while (temp != null)
{
System.out.println(temp.data);
temp = temp.link;
}
}
public void addAfterCurrent(T aData)
{
if (current == null)
return;
ListNode newNode = new ListNode(aData, current.link);
current.link = newNode;
this.size++;
}
public T getCurrent()
{
if(current == null)
return null;
return current.data;
}
public void setCurrent(T aData)
{
if(aData == null || current == null)
return;
current.data = aData;
}
public void gotoNext()
{
if(current == null)
return;
previous = current;
current = current.link;
}
public void reset()
{
current = head;
previous = null;
}
public boolean hasMore()
{
return current != null;
}
public void removeCurrent()
{
if (current == head)
{
head = head.link;
current = head;
}
else
{
previous.link = current.link;
current = current.link;
}
if (this.size > 0)
size--;
}
public int getSize()
{
return this.size;
}
public T getAt(int index)
{
if(index < 0 || index >= size)
return null;
ListNode temp = head;
for(int i=0;i<index;i++)
temp = temp.link;
return temp.data;
}
public void setAt(int index, T aData)
{
if(index < 0 || index >= size || aData == null)
return;
ListNode temp = head;
for (int i = 0; i < index; i++)
temp = temp.link;
temp.data = aData;
}
public T search() throws FileNotFoundException {
Scanner keyboard = new Scanner(System.in);
System.out.println("Search: ");
String query = keyboard.nextLine();
ListNode temp = head;
while(!temp.equals(query))
temp = temp.link;
return temp.data;
//plus some sort of print function to display the result in the console
}
}
You can apply regex for every node's content, if the data type is string apply it if it is of some other datatype convert it into string if possible, else throw some exceptions.
I was doing this exercice:
Write code to partition a linked list around a value x, such that all nodes less than x come before all nodes greater than or equal to x. Example input: 3 -> 5 -> 8 -> 5 -> 10 -> 2 -> 1 output: 3 -> 1 -> 2 -> 10 -> 5 -> 5 -> 8
I found it hard to find a solution for Singly linked list (that created by my own, not using library), I would like to know if there is uncessary code blocks in my code and is there a way to avoid putting in two lists and then merge? because it seems to have very slow performance like that.
public CustomLinkedList partition(CustomLinkedList list, int x) {
CustomLinkedList beforeL = new CustomLinkedList();
CustomLinkedList afterL = new CustomLinkedList();
LinkedListNode current = list.getHead();
while (current != null) {
if (current.getData() < x) {
addToLinkedList(beforeL, current.getData());
} else {
addToLinkedList(afterL, current.getData());
}
// increment current
current = current.getNext();
}
if (beforeL.getHead() == null)
return afterL;
mergeLinkedLists(beforeL, afterL);
return beforeL;
}
public void addToLinkedList(CustomLinkedList list, int value) {
LinkedListNode newEnd = new LinkedListNode(value);
LinkedListNode cur = list.getHead();
if (cur == null)
list.setHead(newEnd);
else {
while (cur.getNext() != null) {
cur = cur.getNext();
}
cur.setNext(newEnd);
cur = newEnd;
}
}
public void mergeLinkedLists(CustomLinkedList list1, CustomLinkedList list2) {
LinkedListNode start = list1.getHead();
LinkedListNode prev = null;
while (start != null) {
prev = start;
start = start.getNext();
}
prev.setNext(list2.getHead());
}
CustumLinkedList contains two attributes: -LinkedListNode which is the head and an int which is the size.
LinkedListNode contains two attributes: One of type LinkedListNode pointing to next node and one of type int: data value
Thank you.
The problem of your code is not merging two lists as you mentioned. It's wrong to use the word merge here because you're only linking up the tail of the left list with head of right list which is a constant time operation.
The real problem is - on inserting a new element on the left or right list, you are iterating from head to tail every time which yields in-total O(n^2) operation and is definitely slow.
Here I've wrote a simpler version and avoid iterating every time from head to insert a new item by keeping track of the current tail.
The code is very simple and is definitely faster than yours(O(n)). Let me know if you need explanation on any part.
// I don't know how your CustomLinkedList is implemented. Here I wrote a simple LinkedList node
public class ListNode {
private int val;
private ListNode next;
public ListNode(int x) {
val = x;
}
public int getValue() {
return this.val;
}
public ListNode getNext() {
return this.next;
}
public void setNext(ListNode next) {
this.next = next;
}
}
public ListNode partition(ListNode head, int x) {
if(head == null) return null;
ListNode left = null;
ListNode right = null;
ListNode iterL = left;
ListNode iterR = right;
while(iter != null) {
if(iter.getValue() < x) {
iterL = addNode(iterL, iter.getValue());
}
else {
iterR = addNode(iterR, iter.getValue());
}
iter = iter.getNext();
}
// link up the left and right list
iterL.setNext(iterR);
return left;
}
public ListNode addNode(ListNode curr, int value) {
ListNode* newNode = new ListNode(value);
if(curr == null) {
curr = newNode;
} else {
curr.setNext(newNode);
curr = curr.getNext();
}
return curr;
}
Hope it helps!
If you have any list of data, access orderByX Method.
Hope it would help you.
public class OrderByX {
Nodes root = null;
OrderByX() {
root = null;
}
void create(int[] array, int k) {
for (int i = 0; i < array.length; ++i) {
root = insert(root, array[i]);
}
}
Nodes insert(Nodes root, int data) {
if (root == null) {
root = new Nodes(data);
} else {
Nodes tempNew = new Nodes(data);
tempNew.setNext(root);
root = tempNew;
}
return root;
}
void display() {
Nodes tempNode = root;
while (tempNode != null) {
System.out.print(tempNode.getData() + ", ");
tempNode = tempNode.getNext();
}
}
void displayOrder(Nodes root) {
if (root == null) {
return;
} else {
displayOrder(root.getNext());
System.out.print(root.getData() + ", ");
}
}
Nodes orderByX(Nodes root, int x) {
Nodes resultNode = null;
Nodes lessNode = null;
Nodes greatNode = null;
Nodes midNode = null;
while (root != null) {
if (root.getData() < x) {
if (lessNode == null) {
lessNode = root;
root = root.getNext();
lessNode.setNext(null);
} else {
Nodes temp = root.getNext();
root.setNext(lessNode);
lessNode = root;
root = temp;
}
} else if (root.getData() > x) {
if (greatNode == null) {
greatNode = root;
root = root.getNext();
greatNode.setNext(null);
} else {
Nodes temp = root.getNext();
root.setNext(greatNode);
greatNode = root;
root = temp;
}
} else {
if (midNode == null) {
midNode = root;
root = root.getNext();
midNode.setNext(null);
} else {
Nodes temp = root.getNext();
root.setNext(midNode);
midNode = root;
root = temp;
}
}
}
resultNode = lessNode;
while (lessNode.getNext() != null) {
lessNode = lessNode.getNext();
}
lessNode.setNext(midNode);
while (midNode.getNext() != null) {
midNode = midNode.getNext();
}
midNode.setNext(greatNode);
return resultNode;
}
public static void main(String... args) {
int[] array = { 7, 1, 6, 2, 8 };
OrderByX obj = new OrderByX();
obj.create(array, 0);
obj.display();
System.out.println();
obj.displayOrder(obj.root);
System.out.println();
obj.root = obj.orderByX(obj.root, 2);
obj.display();
}
}
class Nodes {
private int data;
private Nodes next;
Nodes(int data) {
this.data = data;
this.next = null;
}
public Nodes getNext() {
return next;
}
public void setNext(Nodes next) {
this.next = next;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
I think that maintaining two lists is not an issue. It is possible to use a single list, but at the cost of loosing some of the simplicity.
The principal problem seems to be the addToLinkedList(CustomLinkedList list, int value) method.
It iterates throughout the entire list in order to add a new element.
One alternative is to always add elements at the front of the list. This would also produce a valid solution, and would run faster.
I have a programming challenge that is to recursively multiple the data in the nodes of the list following it. For example
2 - 4 - 6 - 8
will be
384 - 192- 48 - 8
This is what I have done so far in the void product method. I keep getting a null pointer exception. What is wrong with my product method
class Node
{
private int data;
private Node next;
private Node prev;
public Node(int newData,Node newNext,Node newPrev)
{
data = newData;
next = newNext;
prev = newPrev;
}
public int getData()
{
return data;
}
public void setData(int otherData)
{
this.data = otherData;
}
public Node getNext()
{
return next;
}
public Node getPrev()
{ return prev;
}
public void setNext(Node newNext)
{
next = newNext;
}
public void setPrev(Node newPrev)
{
prev = newPrev;
}
}
class LinkedList
{
private Node head;
private Node start;
private Node end;
public LinkedList()
{
head = null;
start = null;
end = null;
}
public void insert(int data)
{
Node newNode = new Node(data,null,null);
if(start == null)
{
start = newNode;
end = start;
}
else
{
newNode.setPrev(end);
end.setNext(newNode);
end = newNode;
}
}
public void product()
{
product(head);
}
public void product(Node head)
{
Node next = head.getNext();
if(head == null)
{
return;
}
else
{
int data = head.getData() * next.getData();
head.setData(data);
product(head.getNext());
}
}
}
You are calling head.getNext() and next.getData() without checking if either of head or next is null, so the program will crash when processing the last node. Even so, you are only multiplying two consecutive items and not accumulating the product.
You can make use of the function's return value to accumulate the right answer:
public void product()
{
product(head);
}
public int product(Node head)
{
if(head == null)
{
return 1;
}
else
{
int data = head.getData() * product(head.getNext());
head.setData(data);
return data;
}
}
I didn't check the logic of your entire code, but the first thing that comes to mind is that you assign:
Node next = head.getNext();
And then you check if(head == null) but what about if(next == null)?
If it is, then you have your error right here:
next.getData()
Because head can be non-null, but its next can certainly be null.
The correct course of action would be to first check if(head == null), then assign Node next = head.getNext();, and then check if(next == null).
First, you call getNext() method on head and then you check if head is null? That is clearly wrong.
You should first check if head is null. Then you should check if next is null.
Also I don't think your recursion will compute the product correctly, since you multiply the data in your current head with what's currently in next - you could achieve that with a simple loop.
Instead you should call product(next) first and compute product later. Like this (didn't test it though)
public void product(Node head)
{
if (head == null)
return;
Node next = head.getNext();
product(next);
if (next != null)
{
int data = head.getData() * next.getData();
head.setData(data);
}
}
This custom class mimics the functionality of Java's LinkedList Class except it only takes integers and obviously lacks most of the functionality. For this one method, removeAll(), I am to go through each node for the list and remove all nodes with that value. My problem is that when the first node in the list contains the value to be removed, it then ignores all subsequent nodes that also contain that value. What seems to be the problem? Am I removing the front node the wrong way? For example, [1]->[1]->[1] should return an empty list, but it leaves the front node and I get [1]
edit: it seems to fail to remove the second node instead of the first.
This is the class (Stores ListNodes as a list):
public class LinkedIntList {
private ListNode front; // first value in the list
// post: constructs an empty list
public LinkedIntList() {
front = null;
}
// post: removes all occurrences of a particular value
public void removeAll(int value) {
ListNode current = front; // primes loop
if (current == null) { // If empty list
return;
}
if (front.data == value) { // If match on first elem
front = current.next;
current = current.next;
}
while (current.next != null) { // If next node exists
if (current.next.data == value) { // If match at next value
current.next = current.next.next;
} else { // If not a match
current = current.next; // increment to next
}
}
}
// post: appends the given value to the end of the list
public void add(int value) {
if (front == null) {
front = new ListNode(value);
} else {
ListNode current = front;
while (current.next != null) {
current = current.next;
}
current.next = new ListNode(value);
}
}
// Sets a particular index w/ a given value
public void set(int index, int value) {
ListNode current = front;
for (int i = 0; i < index; i++) {
current = current.next;
}
current.data = value;
}
}
Here is the ListNode class (responsible for a single "node"):
//ListNode is a class for storing a single node of a linked
//list. This node class is for a list of integer values.
public class ListNode {
public int data; // data stored in this node
public ListNode next; // link to next node in the list
// 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) {
this.data = data;
this.next = next;
}
}
The [1] element that actually stays in the list is the second element which becomes the front element in your code:
if (front.data == value) { // If match on first elem
front = current.next;
current = current.next;
}
After that you just iterate over the list and remove the matching elements.
Replacing the problematic code with this should do the work:
while (front.data == value) { // If match on first elem
front = front.next;
if (front == null) {
return;
}
}
One of the simplest and cleanest way to remove element from a custom Linked list is as follows.
import java.util.concurrent.atomic.AtomicInteger;
public class LinkedList<T> {
class Node<T> {
private T data;
private Node<T> next;
Node(T data) {
this.data = data;
this.next = null;
}
}
private Node<T> head;
private Node<T> tail;
private AtomicInteger size = new AtomicInteger();
public void add(T data) {
Node<T> n = new Node<T>(data);
if (head == null) {
head = n;
tail = n;
size.getAndIncrement();
} else {
tail.next = n;
tail = n;
size.getAndIncrement();
}
}
public int size() {
return size.get();
}
public void displayElement() {
while (head.next != null) {
System.out.println(head.data);
head = head.next;
}
System.out.println(head.data);
}
public void remove(int position) throws IndexOutOfBoundsException {
if (position > size.get()) {
throw new IndexOutOfBoundsException("current size is:" + size.get());
}
Node<T> temp = head;
for (int i = 0; i < position; i++) {
temp = temp.next;
}
head = null;
head = temp;
size.getAndDecrement();
}
}
I have a project where I have to write a bunch of sort methods and measure the time complexity for each, and output the results to an output text file. the program runs but i get some null pointer exceptions in bubblesort method. here is my code and error, if you can tell me how to fix my sort methods, that would be awesome!
linked list class:
public class LinkedList {
protected static class Node {
Comparable item;
Node prev, next;
public Node(Comparable newItem, Node prev, Node next) {
this.item = newItem;
this.prev = prev;
this.next = next;
}
public Node (Comparable newItem) {
this(newItem, null, null);
}
public Node() {
this(null, null, null);
}
public String toString() {
return String.valueOf(item);
}
}
private Node head;
private int size;
public int dataCompares, dataAssigns;
public int loopCompares, loopAssigns;
public int other;
public LinkedList() {
head = new Node(null, null, null);
head.prev = head;
head.next = head;
size = 0;
}
public boolean add(Comparable newItem) {
Node newNode = new Node(newItem);
Node curr;
if(isEmpty()) {
head.next = newNode;
head.prev = newNode;
newNode.next = head;
newNode.prev = head;
} else {
newNode.next = head;
newNode.prev = head.prev;
head.prev.next = newNode;
head.prev = newNode;
}
size++;
return false;
}
public boolean remove(Comparable item) {
if(!isEmpty()) {
Node prev = null;
Node curr = head;
while(curr!=null) {
if(curr.item.compareTo(item)==0) {
if(prev==null) {
head=curr.next;
} else {
prev.next = curr.next;
curr=curr.next;
}
size--;
return true;
}else{
prev=curr;
curr = curr.next;
}
}
}
return false;
}
public void removeAll() {
this.head.prev = null;
this.head.next = null;
size = 0;
}
public boolean isEmpty() {
return size == 0;
}
public boolean remove(Object item) {
return true;
}
public void insertSortNode() {
Node back = head;
if (size < 2)
return;
back = back.next; // SECOND entry in the list
while ( back != null ) { // I.e., end-of-list
Comparable value = back.item;
Node curr = head; // Start at the front
// Find insertion point for value;
while (curr != back && value.compareTo(curr.item) >= 0)
curr = curr.next;
// Propogate values upward, inserting the value from back
while (curr != back){
Comparable hold = curr.item;
curr.item = value;
value = hold;
curr = curr.next;
}
back.item = value; // Drop final value into place!
back = back.next; // Move sorted boundary up
}
} // end insertSort()
public void selSort() {
Node front = head;
// Nothing to do on an empty list
if ( front == null )
return;
while ( front.next != null ) { // skips a one-entry list
Node tiny = front;
Node curr = front.next;
Comparable temp = front.item; // start the swap
for ( ; curr != null ; curr = curr.next ) {
if ( tiny.item.compareTo(curr.item) > 0 )
tiny = curr;
}
front.item = tiny.item; // Finish the swap
tiny.item = temp;
front = front.next; // Advance to the next node
}
// The structure is unchanged, so the validity of tail is unchanged.
}
public void bubbleSort() {
Node Trav=head.next;
Node Trail=head.next;
Comparable temp;
if (Trav != null)
Trav = Trav.next;
while(Trav!=null) {
if (Trav.item.compareTo(Trail.item)<0) {
temp = Trail.item;
Trail.item=Trav.item;
Trav.item = temp;
}
Trail=Trav;
Trav=Trav.next;
}
}
public void insertSortArray() {
Node insert1, cur, tmp1;
Comparable temp;
for(insert1 = this.head.next.next; insert1!=this.head; insert1 = insert1.next) {
//++loopcompares; ++loopassigns;
for (cur = head.next; cur!=insert1; cur=cur.next) {
//++loopCompares; ++loopassigns;
//++datacompares;
if(insert1.item.compareTo(cur.item)<0) {
temp=insert1.item;
//++dataassign
tmp1=insert1;
//++other
while(tmp1!=cur.prev) {
//++loopcomares
tmp1.item=tmp1.prev.item;
tmp1=tmp1.prev;
//++dataassign+=2
}
//++loopcompares
cur.item = temp;
//++dataassign;
break;
}
}
//++loopcompares; ++loopassigns;
}
//++loopcompares; ++loopassigns
}
public void disp6sortsFile(boolean disp, String fileName, String header, String data) {
FileWriter fw = null;
PrintWriter pw = null;
try {
File file = new File(fileName);
fw = new FileWriter(file, true);
pw = new PrintWriter(fw, true);
} catch (IOException e) {
System.err.println("File open failed for " +fileName+ "\n" + e);
System.exit(-1);
}
if (disp) {
pw.print(header + "\n");
}
pw.print(data + "\n");
pw.close();
}
}
here is my error:
Exception in thread "main" java.lang.NullPointerException
at LinkedList.bubbleSort(LinkedList.java:149)
at LinkListTester.main(LinkListTester.java:51)
the linkedlisttester error is simply list1.bubbleSort(); so bubble sort is the problem.
Change:
public String toString() {
return this.item.toString();
}
to:
public String toString() {
return String.valueOf(item); // Handle null too.
}
For add return true. Might check that item is not null if so desired.
remove is written for a single linked list.
In remove the head has a null item, which might have caused the error. Also as we have a circular list with a dummy node for head, the termination should not test for null but head. Otherwise a not present item will loop infinitely.
public boolean remove(Comparable item) {
if(!isEmpty()) {
Node prev = null;
Node curr = head.next; // !
while(curr!=head) { // !
if(curr.item.compareTo(item)==0) {
if(prev==null) { // ! WRONG, but I will not correct home work ;)
head=curr.next;
} else {
prev.next = curr.next;
curr=curr.next;
}
size--;
return true;
}else{
prev=curr;
curr = curr.next;
}
}
}
return false;
}
swap is written for a single linked list.
And here I stopped reading, as I've come to the usages.
Second Edit:
All algorithmic functions, i.e. bubbleSort, have the following control flow:
while(Trav!=null) { ... Trav = Trav.next; }
But the data structure is defined cyclic, so eventually you arrive back at head and there the item is null.
The solution is to have for the first Node a prev null, and for the last Node a next null.
To make this clear, readable, you could substitute the Node head with:
Node first;
Node last;