/*
* eXist Open Source Native XML Database
* Copyright (C) 2009 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*/
package org.exist.util;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.exist.dom.persistent.NodeProxy;
/**
* This class implements a simple version
* of the heapsort algorithm.
* <p>
* This work was undertaken as part of the development of the taxonomic
* repository at http://biodiversity.org.au . See <A
* href="ghw-at-anbg.gov.au">Greg Whitbread</A> for further details.
*
* @author pmurray@bigpond.com
* @author pmurray@anbg.gov.au
* @author https://sourceforge.net/users/paulmurray
* @author http://www.users.bigpond.com/pmurray
*/
public final class HeapSort {
/*
* Briefly: we impose a tree structure on an array by treating the "child"
* nodes of node N as nodes N2 and N2+1. Obviously, the root of the tree is
* node 1.
*
* A "valid" tree has the property that both child nodes of every node have
* a value <= the value of the node. Note that this is considerably weaker
* than the tree being sorted.
*
* The "heap fix" routine does the following: assume that the trees rooted
* at location 2 and 3 are valid but that the node at location 1 is any value.
* While the node of interest is not greater than both its child nodes, move it
* down into the tree by swapping it with the greater of its two child nodes.
*
* This class has additional complications in that we cannot assume that
* our "heap" starts at index 0, because the top-level sorts may be asked
* to sort a subsection of an array.
*/
public static <C extends Comparable<? super C>> void sort(C[] a, int lo, int hi) {
// Establish the heap property.
for (int i=hi-1; i>=lo; i--)
fixHeap(a,lo,i,hi);
// Now place the largest element last,
// 2nd largest 2nd last, etc.
while(lo < hi) {
// a[lo] is the next-biggest element.
SwapVals.swap(a,lo,hi);
// Heap shrinks by 1 element.
hi--;
fixHeap(a,lo,lo,hi);
}
}
public static <C extends Comparable<? super C>> void sort(C[] a, int lo, int hi, int[] b) {
// Establish the heap property.
for (int i=hi-1; i>=lo; i--)
fixHeap(a,b,lo,i,hi);
// Now place the largest element last,
// 2nd largest 2nd last, etc.
while(lo < hi) {
// a[lo] is the next-biggest element.
SwapVals.swap(a,lo,hi);
if(b!=null)
{SwapVals.swap(b,lo,hi);}
// Heap shrinks by 1 element.
hi --;
fixHeap(a,b,lo,lo,hi);
}
}
public static <C> void sort(C[] a, Comparator<C> c, int lo, int hi) {
// Establish the heap property.
for (int i=hi-1; i>=lo; i--)
fixHeap(a,c,lo,i,hi);
// Now place the largest element last,
// 2nd largest 2nd last, etc.
while(lo < hi) {
// a[lo] is the next-biggest element.
SwapVals.swap(a,lo,hi);
// Heap shrinks by 1 element.
hi--;
fixHeap(a,c,lo,lo,hi);
}
}
public static <C extends Comparable<? super C>> void sort(List<C> a, int lo, int hi) {
// Establish the heap property.
for (int i=hi-1; i>=lo; i--)
fixHeap(a,lo,i,hi);
// Now place the largest element last,
// 2nd largest 2nd last, etc.
while(lo<hi) {
// a[lo] is the next-biggest element.
SwapVals.swap(a,lo,hi);
// Heap shrinks by 1 element.
hi --;
fixHeap(a,lo,lo,hi);
}
}
public static void sort(long[] a, int lo, int hi, Object b[]) {
// Establish the heap property.
for (int i=hi-1; i>=lo; i--)
fixHeap(a,b,lo,i,hi);
// Now place the largest element last,
// 2nd largest 2nd last, etc.
while(lo<hi) {
// a[lo] is the next-biggest element.
SwapVals.swap(a,lo,hi);
if(b!=null)
{SwapVals.swap(b,lo,hi);}
// Heap shrinks by 1 element.
hi --;
fixHeap(a,b,lo,lo,hi);
}
}
public static void sortByNodeId(NodeProxy[] a, int lo, int hi) {
// Establish the heap property.
for (int i=hi-1; i>=lo; i--)
fixHeapByNodeId(a,lo,i,hi);
// Now place the largest element last,
// 2nd largest 2nd last, etc.
while(lo<hi) {
// a[lo] is the next-biggest element.
SwapVals.swap(a,lo,hi);
// Heap shrinks by 1 element.
hi --;
fixHeapByNodeId(a,lo,lo,hi);
}
}
private static <C extends Comparable<? super C>> void fixHeap(C[] a, int root, int item, int end) {
for(;;) {
int child = (item-root) * 2 + 1 + root;
if((child > end || a[item].compareTo(a[child])>=0)
&&(child+1 > end || a[item].compareTo(a[child+1])>=0)) {return;}
if(child+1>end || a[child].compareTo(a[child+1])>=0) {
SwapVals.swap(a, item, child);
item = child;
} else {
SwapVals.swap(a, item, child+1);
item = child+1;
}
}
}
private static <C extends Comparable<? super C>> void fixHeap(C[] a, int[] b, int root, int item, int end) {
for(;;) {
int child = (item-root) * 2 + 1 + root;
if((child > end || a[item].compareTo(a[child])>=0)
&&(child+1 > end || a[item].compareTo(a[child+1])>=0)) {return;}
if(child+1>end || a[child].compareTo(a[child+1])>=0) {
SwapVals.swap(a, item, child);
if(b!=null) {SwapVals.swap(b, item, child);}
item = child;
} else {
SwapVals.swap(a, item, child+1);
if(b!=null) {SwapVals.swap(b, item, child+1);}
item = child+1;
}
}
}
private static <C> void fixHeap(C[] a, Comparator<C> c, int root, int item, int end) {
for(;;) {
int child = (item-root) * 2 + 1 + root;
if((child > end || c.compare( a[item],a[child])>=0)
&&(child+1 > end || c.compare(a[item],a[child+1])>=0)) {return;}
if(child+1>end || c.compare(a[child],a[child+1])>=0) {
SwapVals.swap(a, item, child);
item = child;
} else {
SwapVals.swap(a, item, child+1);
item = child+1;
}
}
}
private static <C extends Comparable<? super C>> void fixHeap(List<C> a, int root, int item, int end) {
for(;;) {
int child = (item-root) * 2 + 1 + root;
if((child > end || a.get(item).compareTo(a.get(child))>=0)
&&(child+1 > end || a.get(item).compareTo(a.get(child+1))>=0)) {return;}
if(child+1>end || a.get(child).compareTo(a.get(child+1))>=0) {
SwapVals.swap(a, item, child);
item = child;
} else {
SwapVals.swap(a, item, child+1);
item = child+1;
}
}
}
private static void fixHeap(long[] a, Object[] b, int root, int item, int end) {
for(;;) {
int child = (item-root) * 2 + 1 + root;
if((child > end || a[item]>=a[child])
&&(child+1 > end || a[item]>=a[child+1])) {return;}
if(child+1>end || a[child]>=a[child+1]) {
SwapVals.swap(a, item, child);
if(b!=null) {SwapVals.swap(b, item, child);}
item = child;
} else {
SwapVals.swap(a, item, child+1);
if(b!=null) {SwapVals.swap(b, item, child+1);}
item = child+1;
}
}
}
private static void fixHeapByNodeId(NodeProxy[] a, int root, int item, int end) {
for(;;) {
int child = (item-root) * 2 + 1 + root;
if((child > end || a[item].getNodeId().compareTo(a[child].getNodeId())>=0)
&&(child+1 > end || a[item].getNodeId().compareTo(a[child+1].getNodeId())>=0)) {return;}
if(child+1>end || a[child].getNodeId().compareTo(a[child+1].getNodeId())>=0) {
SwapVals.swap(a, item, child);
item = child;
} else {
SwapVals.swap(a, item, child+1);
item = child+1;
}
}
}
public static void main(String[] args) throws Exception {
final List<String> l = new ArrayList<String>();
if(args.length==0) {
final String[] a=new String[] {
"Rudi",
"Herbert",
"Anton",
"Berta",
"Olga",
"Willi",
"Heinz" };
for (int i = 0; i < a.length; i++)
l.add(a[i]);
} else {
System.err.println("Ordering file "+args[0]+"\n");
try(final java.io.BufferedReader is=new java.io.BufferedReader(new java.io.FileReader(args[0]))) {
String rr;
while((rr=is.readLine())!=null) {
l.add(rr);
}
}
}
long a;
long b;
a=System.currentTimeMillis();
sort(l, 0, l.size() - 1);
b=System.currentTimeMillis();
System.err.println("Ellapsed time: "+(b-a)+" size: "+l.size());
for (int i = 0; i < l.size(); i++)
System.out.println(l.get(i));
}
}