Sort Method for Doubly Linked List - java

Trying to figure out how to sort my doubly linked list.
I get a null pointer exception here:
while (temp.getNext()!=null){
Is there a better approach or any advice to get this going the right way?
public void sort() {
//bubble sort!
boolean swapped = (head != null);
while (swapped) {
swapped = false;
EntryNode temp = head;
//can't swap something with nothing
while (temp.getNext()!=null){
if (temp.getLastName().compareTo(temp.getNext().getLastName()) > 0) {
swapped = true;
//special case for two nodes
if (size == 2) {
//reassign head and tail
tail = temp;
head = temp.getNext();
tail.setPrev(head);
head.setNext(tail);
tail.setNext(null);
head.setNext(null);
}
//if swapping is at head
else {
if (temp == head) {
head = temp.getNext();
temp.setNext(head.getNext());
head.getNext().setPrev(temp);
head.setPrev(null);
head.setNext(temp);
temp.setPrev(head);
}
else {
temp.setNext(temp.getNext().getNext());
temp.setPrev(temp.getNext());
temp.getNext().setNext(temp);
temp.getNext().setPrev(temp.getPrev());
}
}
}
//loop through list
temp = temp.getNext();
}
}
}

Use the merge sort algorithm, is often the best choice for sorting a (single or doubly) linked list. There's already a post discussing the relevant implementation issues.

I think you should check for:
while(temp != null)
because you are already assigning
temp = temp.getNext()
at the end of the while loop.

The simple approach is to put the list contents into an array, use Arrays.sort to sort the array, and finally rebuild the list from the sorted array.

Related

Trouble sorting linked list

outputI'm doing a project for class where I have to sort a linked list using insertion sort. I am supposed to take user input, convert it into an int array and insert it into a linked list. My problem is for some reason when I go to print the linked list post sort, it only prints the first node. The code worked jsut fine when I was initially testing it(I was manually entering what integers to insert), but now that I'm using arrays it doesn't seem to work. Can anyone help?
(this is only one class from my project but let me know if more information is needed).
Edit: I added a picture of what my output lokos like
import java.util.Arrays;
public class SortLL {
static LL top;
static Node head;
static Node sorted;
//function to insert node at head
public void toHead(int newData){
Node newNode = new Node(newData);
newNode.link = head;
head = newNode;
}
public static void insertion(Node ref){ //problem right now is that i'm only passing in one node
sorted = null;
Node current = ref;
while(current != null){
Node next = current.link;
sortInsert(current);
current = next;
}
head = sorted;
}
static void sortInsert(Node newNode){ //item in this case is val
if(sorted == null || sorted.item >= newNode.item){
newNode.link = sorted;
sorted = newNode;
} else {
Node current = sorted;
while(current.link != null && current.link.item < current.item){
current = current.link;
}
newNode.link = current.link;
current.link = newNode;
}
}
void printList(Node head)
{
while (head != null)
{
System.out.print(head.item + " ");
head = head.link;
}
}
public static void sortList(int[] arrA, int[] arrB){
int[] arr = new int[arrA.length + arrB.length];
System.arraycopy(arrA, 0, arr, 0, arrA.length);
System.arraycopy(arrB, 0, arr, arrA.length, arrB.length);
System.out.println("checking array " + Arrays.toString(arr));
SortLL sort = new SortLL();
for(int i=0;i<arr.length;i++){
sort.toHead(arr[i]);
}
System.out.println("sortLL.java\n\n");
sort.printList(sort.head);
sort.sortInsert(sort.head);
System.out.println("\nLinkedList After sorting");
sort.printList(sort.head);
}
}
Inside your printList() method, you shift the head variable while iterating over the list. When you move the head variable to the end, you essentially destroy the linked list since you lose your reference to the beginning of it. Java will then automatically treat the unreferenced nodes as garbage.
From what I see, after you first call sort.printList(sort.head), you destroyed your original linked list, so it didn't work when sorting.
When calling printList(), it might help to use a temporary node (Node temp = head) so that you don't lose your original head variable.

Removing an element by index in a linked list

A method for removing an element from a linked list has been implemented:
public void remove(T e) {
Node<T> node = first;
Node<T> prevNode = null;
while(node != null){
if(e.equals(node)){
if(prevNode == null) {
first = node.next;
}
else {
prevNode.next = node.next;
}
size--;
}
else {
prevNode = node;
}
node = node.next;
}
}
How to correctly implement deleting an element by index? Using the capabilities of the remove method.
public void removeByIndex(int i) {
remove(i);
}
Something like this should work:
public void remove(int i) {
if (i >= size || i < 0) {
throw new ArrayIndexOutOfBoundsException();
}
Node<T> remove;
if (i == 0) {
remove = first;
first = first.next;
first.prev = null; // <- For double linked list
} else {
Node<T> node = first;
for (int j = 0; j < i - 1; ++j) {
node = node.next;
}
remove = node.next;
if (i == size - 1) {
node.next = null;
} else {
node.next.next.prev = node; // <- For double linked list
node.next = node.next.next;
}
}
// Clear links from removed Node
remove.next = null;
remove.prev = null; // <- For double linked list
size--;
}
Find the node before position i. Point that node to the "over next" node.
Edit
The original code example was a rough sketch at best. Updated with a more complete version.
Edit #2
Slight improvements:
Clears links from the removed node
Also handles double linked lists
remove(get(i));
This is not the most efficient solution, but a simple one which uses the remove(T) method. You call it with get(i) as the object to be removed - which is the element at the specified index.
Note: This solution has some issues if the list has duplicate values, but in that case you shouldn't use the remove(T) method anyway. If you want it to be safe, iterate to the specified index:
Node<T> node = first;
for(int i=0;i<index;i++){
prevNode=node;
node=node.next;
}
and do this:
node.prev.next=node.next;
node.next.prev=node.prev;
size--;
Of course, this is just a rough implementation. To ensure full compability, you should check if the index is valid and use the unlink(Node) method of LinkedList.
The LinkedList also has an implementation for the remove(int) method:
checkElementIndex(index);
return unlink(node(index));

How to print elements in reverse from a linked list in java?

// my print in normal order
public void printList()
{
ListElem curr = head;
while(curr != null)
{
System.out.print(curr.getData() + "->");
curr = curr.getNext();
}
}
// my attempt to print in reverse order
public void printListRev()
{
ListElem curr = head;
if(curr == null) return;
printListRev();
System.out.print(curr.getData() + " ");
}
Since this method doesn't accept any arguments, I'm not sure how to go about doing this recursively. I am trying to figure out how to print out the elements (strings) in a singly linked list.
it is not that easy to do with a singly linked list, if it was a doubly linked list and you could manage to get last element (tail element), then following up with the reverse order would be easier, but as you are saying it is a singly linked list i suggest you to load all elements into an array in the function in reverse order and print it directly, this is a work around other wise it is not possible... this is my insight
Just iterate over your list and build a string by prepending data of each item:
public void printListRev()
{
ListElem curr = head;
String result = "";
while(curr != null)
{
result = curr.getData() + "->" + result;
curr = curr.getNext();
}
System.out.print(result);
}

Delete a node from Singly Linked list at any index using a single method/function in java

I want to create and delete a node from the singly linked list in java. The deleting method will take the index of node and delete that node.
The logic is working but it is not deleting the node at first index (0) how do i modify this code so that it can delete node at any position without using extra loops. I know that I am using starting index as 1 in code but I can not riddle this that if entered index is zero then how the program can delete the "previousNode" using the same loop. It will require another loop (based on this logic). Is there a way to remove this extra loop
public E deleteNode(int t) throws IndexOutOfBoundsException{
if(size==0)
return null;
if(t>=size)
throw new IndexOutOfBoundsException("Invalid Input");
Node<E> previousNode=head;
Node<E> currentNode=previousNode.getNext();
int currentIndex=1;
while(currentIndex<t){
previousNode=previousNode.getNext();
currentNode=previousNode.getNext();
currentIndex++;
}
previousNode.setNext(currentNode.getNext());
size--;
return currentNode.getElement();
}
If user enters the index 0, then the output of {1,2,3,4} should be {2,3,4} but I get {1,3,4}.
One option would be to handle it as a special case as it requires updating head.
if (t == 0) {
head = head.getNext();
}
//rest of your code..
Node<E> previousNode=head;
//...
Or, you can do like
Node<E> previousNode = null;
Node<E> currentNode = head;
int currentIndex = 0;
while(currentIndex < t) {
previousNode = currentNode;
currentNode = currentNode.getNext();
currentIndex++;
}
if (previousNode == null) { //removing first node
head = head.getNext();
} else {
previousNode.setNext(currentNode.getNext());
}
size--;
return currentNode.getElement();
But anyway you need to handle it as a special case.

Insertion sort using Linked Integer Nodes

Hey there I have been trying to get an insertion sort method to work for a class I'm taking and we have been told to use insertion sort to sort a linked list of integers without using the linked list class already in the Java libraries.
Here is my inner Node class I have made it only singly linked as i don't fully grasp the circular doubly linked list concept yet
public class IntNode
{
public int value;
public IntNode next;
}
And here is my insertion sort method in the IntList class
public IntList Insertion()
{
IntNode current = head;
while(current != null)
{
for(IntNode next = current; next.next != null; next = next.next)
{
if(next.value <= next.next.value)
{
int temp = next.value;
next.value = next.next.value;
next.next.value = temp;
}
}
current = current.next;
}
return this;
}
The problem I am having is it doesn't sort at all it runs through the loops fine but doesn't manipulate the values in the list at all can someone please explain to me what I have done wrong I am a beginner.
you need to start each time from the first Node in your list, and the loop should end with the tail of your list -1
like this
public static IntList Insertion()
{
IntNode current = head;
IntNode tail = null;
while(current != null&& tail != head )
{
IntNode next = current;
for( ; next.next != tail; next = next.next)
{
if(next.value <= next.next.value)
{
int temp = next.value;
next.value = next.next.value;
next.next.value = temp;
}
}
tail = next;
current = head;
}
return this;
}
The insertion operation only works if the list being inserted into is already sorted - otherwise you're just randomly swapping elements. To start out, remove an element from the original list and construct a new list out of it - this list only has one element, hence it is sorted. Now proceed to remove the remaining elements from the original list, inserting them into the new list as you go. At the end the original list will be empty and the new list will be sorted.
I agree with the Zim-Zam opinion also.
The loop invariant of insertion sort also specifies this: "the subarray which is in sorted order".
Below is the code, I implemented for insertion sorting in which I created another linked list that contains the element in sorted order:
Node newList=new Node();
Node p = newList;
Node temp=newList;
newList.data=head.data;
head=head.node;
while(head!=null)
{
if(head.data<newList.data)
{
Node newTemp = new Node();
newTemp.data=head.data;
newTemp.node=newList;
newList=newTemp;
p=newList;
}
else
{
while(newList!=null && head.data>newList.data)
{
temp=newList;
newList=newList.node;
}
Node newTemp = new Node();
newTemp.data=head.data;
temp.node=newTemp;
newTemp.node=newList;
newList=p;
}
head=head.node;
}

Categories