mirror of
https://github.com/moparisthebest/filelists
synced 2024-12-21 23:08:53 -05:00
Implement selection sort and in-place merge sort for RandomAccessFileList
This commit is contained in:
parent
ba0b66ce54
commit
8635874c04
@ -1,6 +1,7 @@
|
||||
package com.moparisthebest.filelist;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@ -11,7 +12,7 @@ public class Main {
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println("str " + new Date());
|
||||
//final List<Long> list = new RandomAccessFileList<>("/home/mopar/raf2.list", new UnsignedLongConverter(5));
|
||||
final List<Long> list = new RandomAccessFileList<>("/home/mopar/raf2.list", LongConverter40Bit.instance);
|
||||
final List<Long> list = new RandomAccessFileList<>("/home/mopar/raf2.list", LongConverter40Bit.instance); list.clear();
|
||||
/*
|
||||
System.out.println(list.get(0));
|
||||
System.out.println(((RandomAccessFileList)list).longSize());
|
||||
@ -35,14 +36,18 @@ public class Main {
|
||||
list.add(99999999999L);
|
||||
System.out.println(list.get(1));
|
||||
list.add(6L);
|
||||
list.add(4L);
|
||||
System.out.println(list);
|
||||
for(long l : list)
|
||||
System.out.println(l);
|
||||
list.sort(Long::compareTo);
|
||||
System.out.println(list);
|
||||
System.out.println("------");
|
||||
//if(true) return;
|
||||
for(long l = 0; l < 1000; ++l)
|
||||
//for(long l = 7; l < 11; ++l)
|
||||
list.add(l);
|
||||
System.out.println(list);
|
||||
list.sort(Long::compareTo);
|
||||
list.sort(Comparator.reverseOrder());
|
||||
System.out.println(list);
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,7 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.AbstractList;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by mopar on 2/9/17.
|
||||
@ -19,7 +18,7 @@ public class RandomAccessFileList<T> extends AbstractList<T> {
|
||||
public RandomAccessFileList(final RandomAccessFile raf, final ByteArrayConverter<T> bac) {
|
||||
Objects.requireNonNull(raf);
|
||||
Objects.requireNonNull(bac);
|
||||
if(bac.numBytes() < 1)
|
||||
if (bac.numBytes() < 1)
|
||||
throw new IllegalArgumentException("bytesPerEntry must be > 0");
|
||||
this.raf = raf;
|
||||
this.buffer = new byte[bac.numBytes()];
|
||||
@ -44,7 +43,7 @@ public class RandomAccessFileList<T> extends AbstractList<T> {
|
||||
|
||||
public T get(final long index) throws IOException {
|
||||
raf.seek(index * buffer.length);
|
||||
if(raf.read(buffer) != buffer.length)
|
||||
if (raf.read(buffer) != buffer.length)
|
||||
throw new IOException("no full buffer to read, corrupted file?");
|
||||
return bac.fromBytes(buffer);
|
||||
}
|
||||
@ -76,7 +75,7 @@ public class RandomAccessFileList<T> extends AbstractList<T> {
|
||||
@Override
|
||||
public T set(final int index, final T o) {
|
||||
try {
|
||||
return this.set((long)index, o);
|
||||
return this.set((long) index, o);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -98,4 +97,132 @@ public class RandomAccessFileList<T> extends AbstractList<T> {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(final Comparator<? super T> c) {
|
||||
try {
|
||||
//this.selectionSort(c);
|
||||
this.inPlaceMergeSort(c);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void selectionSort(final Comparator<? super T> c) throws IOException {
|
||||
// a[0] to a[n-1] is the array to sort
|
||||
final long n = this.longSize(), n1 = n - 1;
|
||||
final byte[] tmp = new byte[this.buffer.length];
|
||||
|
||||
// advance the position through the entire array
|
||||
// (could do j < n-1 because single element is also min element)
|
||||
for (long j = 0; j < n1; ++j) {
|
||||
/* find the min element in the unsorted a[j .. n-1] */
|
||||
|
||||
/* assume the min is the first element */
|
||||
long iMin = j;
|
||||
/* test against elements after j to find the smallest */
|
||||
for (long i = j + 1; i < n; ++i) {
|
||||
// if this element is less, then it is the new minimum
|
||||
// this order is important, we want get(iMin) done last so it's already in buffer below if we need to swap!
|
||||
// in all cases except when iMin is last, in which case we have to seek back and read it, this is less common though usually
|
||||
final T iObj = this.get(i);
|
||||
if (c.compare(iObj, this.get(iMin)) <= 0){
|
||||
// found new minimum; remember its index
|
||||
iMin = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (iMin != j) {
|
||||
//swap(a[j], a[iMin]);
|
||||
|
||||
// buffer already has iMin value in it unless iMin was last value
|
||||
if (iMin == n1) {
|
||||
// grab iMin to buffer
|
||||
raf.seek(iMin * buffer.length);
|
||||
if (raf.read(buffer) != buffer.length)
|
||||
throw new IOException("no full buffer to read, corrupted file?");
|
||||
}
|
||||
|
||||
// grab j to tmp
|
||||
raf.seek(j * buffer.length);
|
||||
if (raf.read(tmp) != buffer.length)
|
||||
throw new IOException("no full buffer to read, corrupted file?");
|
||||
|
||||
//System.out.printf("iMin: %d j: %d buffer: %d tmp: %d%n", iMin, j, bac.fromBytes(buffer), bac.fromBytes(tmp));
|
||||
|
||||
// write buffer to j
|
||||
raf.seek(j * buffer.length);
|
||||
raf.write(buffer);
|
||||
|
||||
// write tmp to iMin
|
||||
raf.seek(iMin * buffer.length);
|
||||
raf.write(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In-Place Merge Sort.
|
||||
* <p>
|
||||
* Building on the algorithm core found in
|
||||
* http://www.cs.ubc.ca/~harrison/Java/MergeSortAlgorithm.java.html
|
||||
* http://penguin.ewu.edu/cscd300/Topic/AdvSorting/MergeSorts/InPlace.html
|
||||
* http://penguin.ewu.edu/cscd300/Topic/AdvSorting/MergeSorts/MergeSort.java
|
||||
*/
|
||||
public void inPlaceMergeSort(final Comparator<? super T> c) throws IOException {
|
||||
this.inPlaceMergeSort(c, 0, this.longSize() - 1);
|
||||
}
|
||||
|
||||
public void inPlaceMergeSort(final Comparator<? super T> c, final long first, final long last) throws IOException {
|
||||
long mid, lt, rt;
|
||||
|
||||
if (first >= last) return;
|
||||
|
||||
mid = (first + last) / 2;
|
||||
|
||||
inPlaceMergeSort(c, first, mid);
|
||||
inPlaceMergeSort(c, mid + 1, last);
|
||||
|
||||
lt = first;
|
||||
rt = mid + 1;
|
||||
// One extra check: can we SKIP the merge?
|
||||
if (c.compare(this.get(mid), this.get(rt)) <= 0)
|
||||
return;
|
||||
|
||||
byte[] tmp = new byte[buffer.length], tmp2 = new byte[buffer.length], tmp3;
|
||||
|
||||
while (lt <= mid && rt <= last) {
|
||||
// Select from left: no change, just advance lt
|
||||
if (c.compare(this.get(lt), this.get(rt)) <= 0)
|
||||
++lt;
|
||||
// Select from right: rotate [lt..rt] and correct
|
||||
else {
|
||||
// buffer contains rt here due to this.get(rt) being called last above, will move to [lt]
|
||||
|
||||
// scoot everything else over one todo: can do this in bigger chunks than buffer.length to speed things up...
|
||||
//System.out.printf("lt: %d, rt: %d, rt-lt: %d, buffer: %d%n", lt, rt, rt-lt, bac.fromBytes(buffer));
|
||||
raf.seek(lt * buffer.length);
|
||||
raf.read(tmp);
|
||||
for(long dst = lt + 1; dst <= lt + (rt - lt); ++dst){
|
||||
//raf.seek(dst * buffer.length);
|
||||
raf.read(tmp2);
|
||||
raf.seek(dst * buffer.length);
|
||||
raf.write(tmp);
|
||||
tmp3 = tmp2;
|
||||
tmp2 = tmp;
|
||||
tmp = tmp3;
|
||||
}
|
||||
|
||||
// write buffer to lt
|
||||
raf.seek(lt * buffer.length);
|
||||
raf.write(buffer);
|
||||
|
||||
// EVERYTHING has moved up by one
|
||||
lt++;
|
||||
mid++;
|
||||
rt++;
|
||||
}
|
||||
}
|
||||
// Whatever remains in [rt..last] is in place
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user