From 8a50a0c9e6832a486f9bcf12b953a3f780240467 Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Fri, 10 Feb 2017 02:55:49 -0500 Subject: [PATCH] Implement heap sort for RandomAccessFileList --- .../filelist/RandomAccessFileList.java | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moparisthebest/filelist/RandomAccessFileList.java b/src/main/java/com/moparisthebest/filelist/RandomAccessFileList.java index 64fdf4b..f308d5d 100644 --- a/src/main/java/com/moparisthebest/filelist/RandomAccessFileList.java +++ b/src/main/java/com/moparisthebest/filelist/RandomAccessFileList.java @@ -102,7 +102,8 @@ public class RandomAccessFileList extends AbstractList { public void sort(final Comparator c) { try { //this.selectionSort(c); - this.inPlaceMergeSort(c); + //this.inPlaceMergeSort(c); + this.heapSort(c); } catch (IOException e) { throw new RuntimeException(e); } @@ -225,4 +226,62 @@ public class RandomAccessFileList extends AbstractList { } // Whatever remains in [rt..last] is in place } + + public void heapSort(final Comparator c) throws IOException { + long n = this.longSize(); + final byte[] tmp = new byte[this.buffer.length]; + + for (long k = n/2; k > 0; k--) { + downheap(c, tmp, k, n); + } + do { + // swap 0 and n - 1 + n = n - 1; + + // grab 0 to tmp + raf.seek(0); + if (raf.read(tmp) != buffer.length) + throw new IOException("no full buffer to read, corrupted file?"); + + // grab n - 1 to buffer + raf.seek(n * buffer.length); + if (raf.read(buffer) != buffer.length) + throw new IOException("no full buffer to read, corrupted file?"); + + // write tmp to n - 1 + raf.seek(n * buffer.length); + raf.write(tmp); + + // write buffer to 0 + raf.seek(0); + raf.write(buffer); + + + downheap(c, tmp, 1, n); + } while (n > 1); + } + + private void downheap(final Comparator c, final byte[] tmp, long k, final long n) throws IOException { + final T t = this.get(k - 1); + // save k - 1 to tmp, already in buffer + System.arraycopy(buffer, 0, tmp, 0, buffer.length); + + while (k <= n/2) { + long j = k + k; + if ((j < n) && (c.compare(this.get(j - 1), this.get(j)) < 0)) { + ++j; + } + if (c.compare(t, this.get(j - 1)) >= 0) { + break; + } else { + // write j - 1 to k - 1, already in buffer from last this.get(j - 1) above + raf.seek((k - 1) * buffer.length); + raf.write(buffer); + k = j; + } + } + // write tmp to k - 1 + raf.seek((k - 1) * buffer.length); + raf.write(tmp); + } }