package ch.fhnw.claudemartin.algd2; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; public class MSList> extends LinkedList { private static final long serialVersionUID = 0XB00B135L; public MSList() { super(); } public void mergeSort() { iteratorPool.clear(); mergeSort(0, size() - 1); iteratorPool.clear(); } protected void mergeSort(int left, int right) { if (left < right) { int middle = (left + right) / 2; mergeSort(left, middle); mergeSort(middle + 1, right); merge(left, middle, right); } } final List helper = new java.util.LinkedList(); private Method checkForComodification; final private LinkedList> iteratorPool = new LinkedList<>(); /** * Return iterator so that itr.nextIndex() == index + 1 and itr.previousIndex() == index. * The iterator is set to that the last returned element is at the given index (if index>=0). * Iterator at beginning of list: getIteratorAt(-1) */ ListIterator getIteratorAt(final int index) { return getIteratorAt(index, null); } /** * Return iterator so that last returned element is at the given index. * The returned iterator will not be the same as not. */ ListIterator getIteratorAt(final int index, ListIterator not) { ListIterator rv = null; if(index == -1) {// this is always fast: rv = (ListIterator) this.iterator(); iteratorPool.add(rv); return rv; } Iterator> poolItr = iteratorPool.iterator(); while(poolItr.hasNext()) { ListIterator itr = poolItr.next(); if(itr == not) continue; try { if(checkForComodification == null) { checkForComodification = itr.getClass().getDeclaredMethod("checkForComodification"); checkForComodification.setAccessible(true); } checkForComodification.invoke(itr); } catch (Exception e) { poolItr.remove(); continue; } if(rv == null) rv = itr; else { int diffItr = Math.abs(itr.nextIndex() - 1 - index); int diffRv = Math.abs(rv.nextIndex() - 1 - index); if(diffItr < diffRv) rv = itr; if(diffItr <= 3) break; // close enough } } if(rv == null) { rv = (ListIterator) iterator(); iteratorPool.add(rv); } while(rv.nextIndex()<=index) rv.next(); if(rv.previousIndex()>index) { while(rv.previousIndex()>index) rv.previous(); rv.previous(); rv.next(); // last returned == get(index) } assert rv.previousIndex() == index; assert rv.nextIndex() == index + 1; return rv; } /** * @param left * Index of leftmost element, first element of left part. * @param middle * Index of last Element of left part. Right part begins at middle+1. * @param right * Index of last Element of right part. */ protected void merge(final int left, final int middle, final int right) { if (left >= right) return; assert middle == (left + right) / 2; helper.clear(); ListIterator i1 = this.getIteratorAt(left-1); int idx1 = left; T o1 = i1.hasNext() ? i1.next() : null; assert o1 == null || this.get(idx1) == o1; ListIterator i2 = this.getIteratorAt(middle, i1); int idx2 = middle + 1; T o2 = i2.hasNext() ? i2.next() : null; assert o2 == null || this.get(idx2) == o2; while (true) { if (o1 == null && o2 == null) { break; } else if (o2 == null || o1 != null && o1.compareTo(o2) <= 0) { helper.add(o1); o1 = idx1++ < middle ? i1.next() : null; } else { helper.add(o2); o2 = idx2++ < right ? i2.next() : null; } } assert helper.size() == (right-left)+1; i1 = this.getIteratorAt(left); for (T el : helper) { i1.set(el); if (i1.hasNext()) i1.next(); } } @SuppressWarnings("unchecked") public MSList clone() { return (MSList) super.clone(); }; @SuppressWarnings({ "unchecked" }) protected MSList[] split() { int half = this.size() / 2; MSList[] rv = new MSList[] { new MSList(), new MSList() }; int index = 0; for (index = 0; index < half; index++) rv[0].add(this.get(index)); for (index = half; index < this.size(); index++) rv[1].add(this.get(index)); return rv; } @Override public String toString() { if (size() < 50) return "MSList(n=" + size() + "; " + Arrays.toString(this.toArray()) + ")"; else return "MSList(n=" + size() + ")"; } }