DulcetAirman icon

Merge-Sort for LinkedList

DulcetAirman | PRO | 09/27/12 07:12:05 AM UTC | 0 ⭐ | 853 👁️ | Never ⏰ | []
Java |

4.89 KB

|

None

|

0 👍

/

0 👎

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<T extends Comparable<? super T>> extends LinkedList<T> {
  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<T> helper = new java.util.LinkedList<T>();
  
  private Method checkForComodification;
  final private LinkedList<ListIterator<T>> 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<T> 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 <i>not</i>.
   */
  ListIterator<T> getIteratorAt(final int index, ListIterator<T> not) {
    ListIterator<T> rv = null;
    if(index == -1) {// this is always fast:
      rv = (ListIterator<T>) this.iterator();
      iteratorPool.add(rv);
      return rv;
    }
    Iterator<ListIterator<T>> poolItr = iteratorPool.iterator();
    while(poolItr.hasNext()) {
      ListIterator<T> 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<T>) 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 <code>middle+1</code>.
   * @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<T> i1 = this.getIteratorAt(left-1);
    int idx1 = left;
    T o1 = i1.hasNext() ? i1.next() : null;
    assert o1 == null || this.get(idx1) == o1;
 
    ListIterator<T> 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<T> clone() {
    return (MSList<T>) super.clone();
  };
 
  @SuppressWarnings({ "unchecked" })
  protected MSList<T>[] split() {
    int half = this.size() / 2;
    MSList<T>[] rv = new MSList[] { new MSList<T>(), new MSList<T>() };
    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() + ")";
  }
}

Comments