/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hh.creditassignment.fitnessindicator;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
/**
* This is a doubly linked list that is used to maintain a sorted list. Sorting
* is O(nlog(n)), look up for max and min are O(1), insertion and deletion is
* O(1), search in sorted list is O(log(n)).
*
* @author SEAK2
*/
public class SortedLinkedList<T> extends LinkedList<T> implements Cloneable{
private static final long serialVersionUID = -6089720372001116175L;
private final Comparator<T> comparator;
/**
* Constructor takes in unsorted list and sorts it. Takes O(nlog(n)) where n
* is number of items in collection
*
* @param unSortedList collection of items to sort
* @param comparator comparator to use to sort
*/
public SortedLinkedList(Collection<T> unSortedList, Comparator<T> comparator) {
super(unSortedList);
this.sort();
this.comparator = comparator;
}
/**
* Constructor to create an empty list
* @param comparator
*/
private SortedLinkedList(Comparator<T> comparator) {
super();
this.comparator = comparator;
}
/**
* Sorts the collection
*/
public final void sort(){
Collections.sort(this, comparator);
}
/**
* Finds index of item in sorted list (smallest value at 0th index) using
* binary search method. This will not return an error if the list is not
* sorted. If list is not sorted, a nonsensical index is returned
*
* @param item the item to find in the list
* @return the index of the item in the list
*/
public int binaryFind(T item) {
return binaryFind(item, 0, this.size());
}
/**
* Finds index of item in sorted list (smallest value at 0th index) with
* maximum and minimum index bounds using binary search method. This will
* not return an error if the list is not sorted. If list is not sorted, a
* nonsensical index is returned
*
* @param item the item to find in the list
* @param min the min of the range to search
* @param max the max of the range to search
* @return the index of the item in the list
*/
public int binaryFind(T item, int min, int max) {
try{
if (max < min) {
throw new IllegalArgumentException("Item not found in list");
} else {
int mid = (max - min) / 2 + min;
if (comparator.compare(this.get(mid), item) == 1) {
return binaryFind(item, min, mid - 1);
} else if (comparator.compare(this.get(mid), item) == -1) {
return binaryFind(item, mid + 1, max);
} else {
return mid;
}
}
}catch(IndexOutOfBoundsException ex){
System.out.println("Item not found in list: Index exceeeded");
throw ex;
}
}
/**
* Finds index to insert item in sorted list (smallest value at 0th index)
* with maximum and minimum index bounds using binary search method. This
* will not return an error if the list is not sorted. If list is not
* sorted, a nonsensical index is returned
*
* @param item the item to insert in the list
* @param min the min of the range to consider for insertion
* @param max the max of the range to consider for insertion
* @return the index to in the list where the item was inserted
*/
private int binaryFindInsert(T item, int min, int max) {
if(flaggedAddFirst(item))
return 0;
else if(flaggedAddLast(item))
return this.size()-1;
else{
int index = recursFindInsert(item, min, max);
super.add(index, item);
for(int i=1;i<this.size();i++){
if(comparator.compare(this.get(i-1), this.get(i))==1)
System.out.println("");
}
return index;
}
}
private int recursFindInsert(T item, int min, int max){
if (max - min < 2) {
// if (comparator.compare(this.get(min), item) == 1) {
// return min;
// } else if (comparator.compare(this.get(min), item) == -1) {
// return max;
// } else {
return min + 1;
// }
} else {
int mid = (max - min) / 2 + min;
if (comparator.compare(this.get(mid), item) == 1) {
return recursFindInsert(item, min, mid);
} else if (comparator.compare(this.get(mid), item) == -1) {
return recursFindInsert(item, mid, max);
} else {
return mid + 1;
}
}
}
@Override
/**
* Can add a collection of items to list, but will sort after addition
*/
public boolean addAll(int i, Collection<? extends T> clctn) {
boolean flag = super.addAll(i, clctn);
this.sort();
return flag;
}
@Override
/**
* Can add a collection of items to list, but will sort after addition
*/
public boolean addAll(Collection<? extends T> clctn) {
boolean flag = super.addAll(clctn);
this.sort();
return flag;
}
@Override
/**
* Will add item in index to maintain sorted list
*/
public boolean add(T e) {
binaryFindInsert(e,0,this.size()-1);
return true;
}
@Override
/**
* Can add to end of list if order is maintained. Otherwise, item is not inserted.
*/
public void addLast(T e) {
flaggedAddLast(e);
}
/**
* Adds to end of list if order is maintained. Boolean returned true if item was added. Else false;
* @param e
* @return
*/
private boolean flaggedAddLast(T e){
int compare = comparator.compare(this.getLast(), e);
if(compare!=1){
super.addLast(e);
return true;
}
return false;
}
@Override
/**
* Can add to head of list if order is maintained. Otherwise, item is not inserted.
*/
public void addFirst(T e) {
flaggedAddFirst(e);
}
/**
* Adds to head of list if order is maintained. Boolean returned true if item was added. Else false;
* @param e
* @return
*/
private boolean flaggedAddFirst(T e) {
if(this.size()==0){
this.add(0, e);
return true;
}
int compare = comparator.compare(this.get(0), e);
if (compare != -1) {
super.addFirst(e);
return true;
}
return false;
}
/**
* Copies the elements within the list to a new list
* @return
*/
@Override
public SortedLinkedList<T> clone(){
SortedLinkedList<T> out = new SortedLinkedList(comparator);
for(int i=0;i<this.size();i++){
out.add(i, this.get(i));
}
return out;
}
}