What is wrong with this linked list? - java

The assignment was to write a function to swap 2 nodes in the list. If the function could swap the nodes regardless of the order, a 10% was awarded. I think my implementation is able to swap 2 elements regardless of the order in the list but I still did not received the bonus marks. Is there anything that I am missing?
I was given a generic node class,
public class Node<T> {
public T val;
public Node<T> next;
public Node(T val) {
this.val = val;
this.next = null;
}
}
I was also given an interface defined as below,
public interface SwapList<T> {
public void add(T val);
/**
* Swaps two elements in the list, but only if #param val1 comes BEFORE #param
* val2. Solve the problem regardless of the order, for 10% extra. list: A B
* C -> swap(A,B) will result in the list B A C list: A B C -> swap(B,A)
* will not swap. list: A C C -> swap(A, D) will throw a
* NoSuchElementException list: A B C B -> swap (A, B) will result in the
* list B A C B list: A B C A B B -> swap (A,B) will result in the list B A
* C A B B a list with one or zero elements cannot do a swap
*/
public void swap(T val1, T val2);
public T get(int i);
}
and I have my own implementation of this interface as below,
import java.util.NoSuchElementException;
public class SwapListImpl<T> implements SwapList<T> {
private Node<T> head;
private Node<T> tail;
private int counter;
public SwapListImpl() {
head = null;
tail = null;
counter = 0;
}
#Override
public void add(T val) {
Node<T> node = new Node<T>(val);
if (head == null) {
head = node;
tail = node;
} else {
tail.next = node;
tail = node;
}
counter++;
}
#Override
public void swap(T val1, T val2) {
if (counter < 2 || val1.equals(val2))
return;
Node<T> current = head;
Node<T> currentPrev = null;
Node<T> first = head;
Node<T> firstPrev = null;
Node<T> firstNext = first.next;
Node<T> second = head;
Node<T> secondPrev = null;
Node<T> secondNext = second.next;
boolean foundFirst = false;
boolean foundSecond = false;
boolean inOrder = false;
while (current != null) {
if (!foundFirst && current.val.equals(val1)) {
firstPrev = currentPrev;
first = current;
firstNext = current.next;
if (!foundSecond)
inOrder = true;
foundFirst = true;
}
if (!foundSecond && current.val.equals(val2)) {
secondPrev = currentPrev;
second = current;
secondNext = current.next;
if (foundFirst)
inOrder = true;
foundSecond = true;
}
if (foundFirst && foundSecond) {
if (!inOrder) {
Node<T> temp = first;
first = second;
second = temp;
temp = firstPrev;
firstPrev = secondPrev;
secondPrev = temp;
temp = firstNext;
firstNext = secondNext;
secondNext = temp;
}
if (firstPrev == null) {
head = second;
if (first == secondPrev) {
second.next = first;
first.next = secondNext;
} else {
second.next = firstNext;
secondPrev.next = first;
first.next = secondNext;
}
} else {
firstPrev.next = second;
first.next = secondNext;
if (first == secondPrev) {
second.next = first;
} else {
second.next = firstNext;
secondPrev.next = first;
}
}
break;
}
currentPrev = current;
current = current.next;
}
if (!foundFirst || !foundSecond) {
throw new NoSuchElementException();
}
}
#Override
public T get(int i) {
if (i < counter) {
Node<T> node = head;
for (int n = 0; n < i; n++) {
node = node.next;
}
return node.val;
} else {
throw new IndexOutOfBoundsException();
}
}
}

I think the problem is the swap itself: you forgot to set the tail.
Here is a small test for exactly that problem:
#Test
public void test() {
SwapListImpl<String> list = new SwapListImpl<String>();
list.add("A");
list.add("B");
list.add("C");
list.swap("A", "C");
assertEquals("C", list.get(0));
assertEquals("C", list.getHead().val);
assertEquals("B", list.get(1));
assertEquals("A", list.get(2));
assertEquals("A", list.getTail().val);
list.add("D");
assertEquals("C", list.get(0));
assertEquals("C", list.getHead().val);
assertEquals("B", list.get(1));
assertEquals("A", list.get(2));
assertEquals("D", list.get(3));
assertEquals("D", list.getTail().val);
list.swap("A", "C");
assertEquals("A", list.get(0));
assertEquals("A", list.getHead().val);
assertEquals("B", list.get(1));
assertEquals("C", list.get(2));
assertEquals("D", list.get(3));
assertEquals("D", list.getTail().val);
list.swap("C", "B");
assertEquals("A", list.get(0));
assertEquals("A", list.getHead().val);
assertEquals("C", list.get(1));
assertEquals("B", list.get(2));
assertEquals("D", list.get(3));
assertEquals("D", list.getTail().val);
}
You see I added two methods to the list, for getting the head and tail, but that's not important - the test would even fail without the explicit test for head and tail. The extra methods for the list are really simple:
public Node<T> getTail() {
return this.tail;
}
public Node<T> getHead() {
return this.head;
}
The problem of not setting tail occurs when swapping the last element of the list and then adding another element.
Here is a fixed version of the actual swap:
if (foundFirst && foundSecond) {
if (second == this.tail) {
this.tail = first;
} else if (first == this.tail) {
this.tail = second;
}
if (first == this.head) {
this.head = second;
} else if (second == this.head) {
this.head = first;
}
if (firstPrev == second) {
first.next = second;
} else {
if (firstPrev != null) {
firstPrev.next = second;
}
first.next = secondNext;
}
if (secondPrev == first) {
second.next = first;
} else {
if (secondPrev != first && secondPrev != null) {
secondPrev.next = first;
}
second.next = firstNext;
}
break;
}
You see I didn't add lines to your code - instead I wrote the code in another way. I think it's more readable, but you also can try just to set the tail in the correct way. But it was too complex for me, so I reduced the complexity of that code - that's the reason why I rewrote it.
I would suggest, that you use first and second for the first/second occurence and not for the first/second argument. I think that would improve the readability of the method. But that's another point ;-)
Hope that helps - so the order IMHO is not the problem, but the tail.

Related

Ordering LinkedList <class> [duplicate]

I am needing to sort a linked list alphabetically. I have a Linked List full of passengers names and need the passengers name to be sorted alphabetically. How would one do this? Anyone have any references or videos?
You can use Collections#sort to sort things alphabetically.
In order to sort Strings alphabetically you will need to use a Collator, like:
LinkedList<String> list = new LinkedList<String>();
list.add("abc");
list.add("Bcd");
list.add("aAb");
Collections.sort(list, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return Collator.getInstance().compare(o1, o2);
}
});
Because if you just call Collections.sort(list) you will have trouble with strings that contain uppercase characters.
For instance in the code I pasted, after the sorting the list will be: [aAb, abc, Bcd] but if you just call Collections.sort(list); you will get: [Bcd, aAb, abc]
Note: When using a Collator you can specify the locale Collator.getInstance(Locale.ENGLISH) this is usually pretty handy.
In java8 you no longer need to use Collections.sort method as LinkedList inherits the method sort from java.util.List, so adapting Fido's answer to Java8:
LinkedList<String>list = new LinkedList<String>();
list.add("abc");
list.add("Bcd");
list.add("aAb");
list.sort( new Comparator<String>(){
#Override
public int compare(String o1,String o2){
return Collator.getInstance().compare(o1,o2);
}
});
References:
http://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html
http://docs.oracle.com/javase/7/docs/api/java/util/List.html
Elegant solution since JAVA 8:
LinkedList<String>list = new LinkedList<String>();
list.add("abc");
list.add("Bcd");
list.add("aAb");
list.sort(String::compareToIgnoreCase);
Another option would be using lambda expressions:
list.sort((o1, o2) -> o1.compareToIgnoreCase(o2));
Here is the example to sort implemented linked list in java without using any standard java libraries.
package SelFrDemo;
class NodeeSort {
Object value;
NodeeSort next;
NodeeSort(Object val) {
value = val;
next = null;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public NodeeSort getNext() {
return next;
}
public void setNext(NodeeSort next) {
this.next = next;
}
}
public class SortLinkList {
NodeeSort head;
int size = 0;
NodeeSort add(Object val) {
// TODO Auto-generated method stub
if (head == null) {
NodeeSort nodee = new NodeeSort(val);
head = nodee;
size++;
return head;
}
NodeeSort temp = head;
while (temp.next != null) {
temp = temp.next;
}
NodeeSort newNode = new NodeeSort(val);
temp.setNext(newNode);
newNode.setNext(null);
size++;
return head;
}
NodeeSort sort(NodeeSort nodeSort) {
for (int i = size - 1; i >= 1; i--) {
NodeeSort finalval = nodeSort;
NodeeSort tempNode = nodeSort;
for (int j = 0; j < i; j++) {
int val1 = (int) nodeSort.value;
NodeeSort nextnode = nodeSort.next;
int val2 = (int) nextnode.value;
if (val1 > val2) {
if (nodeSort.next.next != null) {
NodeeSort CurrentNext = nodeSort.next.next;
nextnode.next = nodeSort;
nextnode.next.next = CurrentNext;
if (j == 0) {
finalval = nextnode;
} else
nodeSort = nextnode;
for (int l = 1; l < j; l++) {
tempNode = tempNode.next;
}
if (j != 0) {
tempNode.next = nextnode;
nodeSort = tempNode;
}
} else if (nodeSort.next.next == null) {
nextnode.next = nodeSort;
nextnode.next.next = null;
for (int l = 1; l < j; l++) {
tempNode = tempNode.next;
}
tempNode.next = nextnode;
nextnode = tempNode;
nodeSort = tempNode;
}
} else
nodeSort = tempNode;
nodeSort = finalval;
tempNode = nodeSort;
for (int k = 0; k <= j && j < i - 1; k++) {
nodeSort = nodeSort.next;
}
}
}
return nodeSort;
}
public static void main(String[] args) {
SortLinkList objsort = new SortLinkList();
NodeeSort nl1 = objsort.add(9);
NodeeSort nl2 = objsort.add(71);
NodeeSort nl3 = objsort.add(6);
NodeeSort nl4 = objsort.add(81);
NodeeSort nl5 = objsort.add(2);
NodeeSort NodeSort = nl5;
NodeeSort finalsort = objsort.sort(NodeSort);
while (finalsort != null) {
System.out.println(finalsort.getValue());
finalsort = finalsort.getNext();
}
}
}
Node mergeSort(Node head) {
if(head == null || head.next == null) {
return head;
}
Node middle = middleElement(head);
Node nextofMiddle = middle.next;
middle.next = null;
Node left = mergeSort(head);
Node right = mergeSort(nextofMiddle);
Node sortdList = merge(left, right);
return sortdList;
}
Node merge(Node left, Node right) {
if(left == null) {
return right;
}
if(right == null) {
return left;
}
Node temp = null;
if(left.data < right.data) {
temp = left;
temp.next = merge(left.next, right);
} else {
temp = right;
temp.next = merge(left, right.next);
}
return temp;
}
Node middleElement(Node head) {
Node slow = head;
Node fast = head;
while (fast != null && fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
I wouldn't. I would use an ArrayList or a sorted collection with a Comparator. Sorting a LinkedList is about the most inefficient procedure I can think of.
You can do it by Java 8 lambda expression :
LinkedList<String> list=new LinkedList<String>();
list.add("bgh");
list.add("asd");
list.add("new");
//lambda expression
list.sort((a,b)->a.compareTo(b));
If you'd like to know how to sort a linked list without using standard Java libraries, I'd suggest looking at different algorithms yourself. Examples here show how to implement an insertion sort, another StackOverflow post shows a merge sort, and ehow even gives some examples on how to create a custom compare function in case you want to further customize your sort.

partition in a singly linked list

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.

Union of Generic Linked List in Java

In this program I made a generic linked list .Insert and Display functions are working fine but the union function is not working.I'm actually not sure that the function which i wrote is correct or not so,How do I perform union of the two given list.
import java.util.*;
class Node<T> {
T data;
Node<T> next;
Node(T d) {
data = d;
}
void display() {
System.out.println(data + " ");
}
}
class List<T> {
Node<T> first;
List() {
first = null;
}
void insert(T data) {
Node<T> newnode = new Node<T>(data);
if (first == null)
first = newnode;
else {
Node<T> temp = first;
while (temp.next != null)
temp = temp.next;
temp.next = newnode;
}
}
void display() {
if (first == null)
System.out.println("EmpTY");
else {
Node<T> temp = first;
while (temp != null) {
temp.display();
temp = temp.next;
}
}
}
public void union(Node<Double> head1, Node<Double> head2) {
Node<T> t = head1;
Node<T> t1 = head2;
while (t != null && t1 != null) {
if (t.data > t1.data) {
System.out.println(t.data + "\n");
t = t.next;
} else if (t.data < t1.data) {
System.out.println(t1.data + "\n");
t1 = t1.next;
} else {
System.out.println(t.data + "\n");
System.out.println(t.data + "\n");
t = t.next;
t1 = t1.next;
}
}
}
}
class DEMO {
public static void main(String args[]) {
List<Double> l1 = new List<Double>();
for (double i = 0; i < 5; i++) {
l1.insert(i);
}
l1.display();
List<Double> l2 = new List<Double>();
List<Double> l3 = new List<Double>();
for (double j = 0; j < 5; j++) {
l2.insert(j);
}
l3.union(l1, l2);
}
}
You can do something like this:
/* Function to get Union of 2 Linked Lists */
void doUnion(Node head1, Node head2) {
Node t1 = head1, t2 = head2;
//insert all elements of list1 in the result
while (t1 != null) {
push(t1.data);
t1 = t1.next;
}
// insert those elements of list2 that are not present
while (t2 != null) {
if (!isPresent(head, t2.data)) {
push(t2.data);
}
t2 = t2.next;
}
}
/* Inserts a node at start of linked list */
void push(int new_data) {
/* 1. Allocate the Node & Put in the data*/
Node new_node = new Node(new_data);
/* 2. Make next of new Node as head */
new_node.next = head;
/* 3. Move the head to point to new Node */
head = new_node;
}
/* A utilty function that returns true if data is present in linked list else return false */
boolean isPresent(Node head, int data) {
Node t = head;
while (t != null) {
if (t.data == data) {
return true;
}
t = t.next;
}
return false;
}

singly linked-list in java implementation

I have being given a task to implement the following method in Java: SubList(S, L) returns true if list S is a sublist of list L.
I need to use the following notation when I process lists as an abstract object in the recurrence relations. Given a list L, we write L = [H|R] where H is the head of the list and R is the rest of the list. For an empty list L, we write L = []. For example, if L = [1, 2, 3, 4, 5], H = 1, and R = [2, 3, 4, 5].
Hence my tasks are:
a) Provide the recurrence relations for SubList(S, L) using the above list notation.
b) Implement the recursive algorithm in Java using the recurrence relations.
Being stuck on this task for a day and a half now and still having trouble how to do this. Appreciate, if anyone can help me to solve this problem.
This is the java code I have been given to work with.
class SLLNode {
public Object info; // This is the data
public SLLNode next; // this is the address of the next node
public SLLNode() { // Here's how we construct an empty list.
next = null;
}
public SLLNode(Object el) {
info = el; next = null;
}
public SLLNode(Object el, SLLNode ptr) {
info = el; next = ptr;
}
}
class SLList {
protected SLLNode head = null;
public SLList() {
}
public void setToNull() {
head = null;
}
public boolean isEmpty() {
return head == null;
}
public Object first() {
return head.info;
}
public SLLNode head() {
return head;
}
public void printAll() {
for (SLLNode tmp = head; tmp != null; tmp = tmp.next)
System.out.print(tmp.info.toString());
}
public void add(Object el) {
head= new SLLNode(el,head);
}
public Object find(Object el) {
SLLNode tmp = head;
for ( ; tmp != null && !el.equals(tmp.info); tmp = tmp.next);
if (tmp == null)
return null;
else return tmp.info;
}
public boolean member(Object el) {
SLLNode tmp = head;
for ( ; tmp != null && !el.equals(tmp.info); tmp = tmp.next);
if (tmp == null)
return false;
else return true;
}
public Object deleteHead() { // remove the head and return its info;
Object el = head.info;
head = head.next;
return el;
}
public void delete(Object el) { // find and remove el;
if (head != null) // if non-empty list;
if (el.equals(head.info)) // if head needs to be removed;
head = head.next;
else {
SLLNode pred = head, tmp = head.next;
for ( ; tmp != null && !(tmp.info.equals(el));
pred = pred.next, tmp = tmp.next);
if (tmp != null) // if found
pred.next = tmp.next;
}
}
}
SubList([], L) = true (1)
SubList(H|[], H|*) = true (2)
SubList(H|[], []) = false (3)
SubList(SH|[], H|R) = SubList(SH|[], H|[]) OR SubList(SH|[], R) (4)
SubList(SH|SR, L) = SubList(SH|[], L) AND SubList(SR, L) (5)
In english, it means that if L contains the first element of your sublist S AND that it contains the remaining elements of the sublist, then your SubList method is gonna return true.
The recursion here visible on the 4th and 5th lines, where you see that we are invoking the same function again and again until SR contains only one element.
Ex:
L = [1,2,5]
S = [1,5]
SubList(S, L) = SubList([1,5], [1,2,5])
= SubList(1|[5], 1|[2,5]) (4+5)
= SubList(1|[], 1|[2,5]) AND SubList([5], 1|[2,5])
= SubList(1|[], 1|[2,5]) AND (SubList(5|[], 1|[]) OR SubList(5|[], [2,5]))
= SubList(1|[], 1|[2,5]) AND (SubList(5|[], 1|[]) OR (SubList(5|[], 2|[]) OR SubList(5|[], [5])))
= SubList(1|[], 1|[2,5]) AND (SubList(5|[], 1|[]) OR (SubList(5|[], 2|[]) OR SubList(5|[], 5|[])))
= true AND (false OR (false OR true))
= true AND true
= true
Possible Java implementation:
public SLList(SLNode h) {
this.head = h;
}
public SLList singletonList(SLNode n) {
return new SLList(new SLNode(n.info));
}
public SLList remainingList(SLNode n) {
if(n == null) return new SLList();
return new SLList(n);
}
private static boolean subList(SLList s, SLList l) {
if(s.isEmpty()) return true;
if(l.isEmpty()) return false;
if(s.head.next == null && l.first().equals(s.first())) return true;
return (subList(singletonList(s.head), singletonList(l.head)) ||
subList(singletonList(s.head), remainingList(l.head.next))) &&
subList(remainingList(s.head.next), l);
}
I haven't tested the code, there might be some null checks missing but the important thing is that you get the idea of how recursion works.

Java how to sort a Linked List?

I am needing to sort a linked list alphabetically. I have a Linked List full of passengers names and need the passengers name to be sorted alphabetically. How would one do this? Anyone have any references or videos?
You can use Collections#sort to sort things alphabetically.
In order to sort Strings alphabetically you will need to use a Collator, like:
LinkedList<String> list = new LinkedList<String>();
list.add("abc");
list.add("Bcd");
list.add("aAb");
Collections.sort(list, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return Collator.getInstance().compare(o1, o2);
}
});
Because if you just call Collections.sort(list) you will have trouble with strings that contain uppercase characters.
For instance in the code I pasted, after the sorting the list will be: [aAb, abc, Bcd] but if you just call Collections.sort(list); you will get: [Bcd, aAb, abc]
Note: When using a Collator you can specify the locale Collator.getInstance(Locale.ENGLISH) this is usually pretty handy.
In java8 you no longer need to use Collections.sort method as LinkedList inherits the method sort from java.util.List, so adapting Fido's answer to Java8:
LinkedList<String>list = new LinkedList<String>();
list.add("abc");
list.add("Bcd");
list.add("aAb");
list.sort( new Comparator<String>(){
#Override
public int compare(String o1,String o2){
return Collator.getInstance().compare(o1,o2);
}
});
References:
http://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html
http://docs.oracle.com/javase/7/docs/api/java/util/List.html
Elegant solution since JAVA 8:
LinkedList<String>list = new LinkedList<String>();
list.add("abc");
list.add("Bcd");
list.add("aAb");
list.sort(String::compareToIgnoreCase);
Another option would be using lambda expressions:
list.sort((o1, o2) -> o1.compareToIgnoreCase(o2));
Here is the example to sort implemented linked list in java without using any standard java libraries.
package SelFrDemo;
class NodeeSort {
Object value;
NodeeSort next;
NodeeSort(Object val) {
value = val;
next = null;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public NodeeSort getNext() {
return next;
}
public void setNext(NodeeSort next) {
this.next = next;
}
}
public class SortLinkList {
NodeeSort head;
int size = 0;
NodeeSort add(Object val) {
// TODO Auto-generated method stub
if (head == null) {
NodeeSort nodee = new NodeeSort(val);
head = nodee;
size++;
return head;
}
NodeeSort temp = head;
while (temp.next != null) {
temp = temp.next;
}
NodeeSort newNode = new NodeeSort(val);
temp.setNext(newNode);
newNode.setNext(null);
size++;
return head;
}
NodeeSort sort(NodeeSort nodeSort) {
for (int i = size - 1; i >= 1; i--) {
NodeeSort finalval = nodeSort;
NodeeSort tempNode = nodeSort;
for (int j = 0; j < i; j++) {
int val1 = (int) nodeSort.value;
NodeeSort nextnode = nodeSort.next;
int val2 = (int) nextnode.value;
if (val1 > val2) {
if (nodeSort.next.next != null) {
NodeeSort CurrentNext = nodeSort.next.next;
nextnode.next = nodeSort;
nextnode.next.next = CurrentNext;
if (j == 0) {
finalval = nextnode;
} else
nodeSort = nextnode;
for (int l = 1; l < j; l++) {
tempNode = tempNode.next;
}
if (j != 0) {
tempNode.next = nextnode;
nodeSort = tempNode;
}
} else if (nodeSort.next.next == null) {
nextnode.next = nodeSort;
nextnode.next.next = null;
for (int l = 1; l < j; l++) {
tempNode = tempNode.next;
}
tempNode.next = nextnode;
nextnode = tempNode;
nodeSort = tempNode;
}
} else
nodeSort = tempNode;
nodeSort = finalval;
tempNode = nodeSort;
for (int k = 0; k <= j && j < i - 1; k++) {
nodeSort = nodeSort.next;
}
}
}
return nodeSort;
}
public static void main(String[] args) {
SortLinkList objsort = new SortLinkList();
NodeeSort nl1 = objsort.add(9);
NodeeSort nl2 = objsort.add(71);
NodeeSort nl3 = objsort.add(6);
NodeeSort nl4 = objsort.add(81);
NodeeSort nl5 = objsort.add(2);
NodeeSort NodeSort = nl5;
NodeeSort finalsort = objsort.sort(NodeSort);
while (finalsort != null) {
System.out.println(finalsort.getValue());
finalsort = finalsort.getNext();
}
}
}
Node mergeSort(Node head) {
if(head == null || head.next == null) {
return head;
}
Node middle = middleElement(head);
Node nextofMiddle = middle.next;
middle.next = null;
Node left = mergeSort(head);
Node right = mergeSort(nextofMiddle);
Node sortdList = merge(left, right);
return sortdList;
}
Node merge(Node left, Node right) {
if(left == null) {
return right;
}
if(right == null) {
return left;
}
Node temp = null;
if(left.data < right.data) {
temp = left;
temp.next = merge(left.next, right);
} else {
temp = right;
temp.next = merge(left, right.next);
}
return temp;
}
Node middleElement(Node head) {
Node slow = head;
Node fast = head;
while (fast != null && fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
I wouldn't. I would use an ArrayList or a sorted collection with a Comparator. Sorting a LinkedList is about the most inefficient procedure I can think of.
You can do it by Java 8 lambda expression :
LinkedList<String> list=new LinkedList<String>();
list.add("bgh");
list.add("asd");
list.add("new");
//lambda expression
list.sort((a,b)->a.compareTo(b));
If you'd like to know how to sort a linked list without using standard Java libraries, I'd suggest looking at different algorithms yourself. Examples here show how to implement an insertion sort, another StackOverflow post shows a merge sort, and ehow even gives some examples on how to create a custom compare function in case you want to further customize your sort.

Categories

Resources