/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.foundation; /** * @exclude */ public class Algorithms4 { private static final int QSORT_LENGTH_THRESHOLD = 7; public static void sort(Sortable4 sortable) { sort(sortable, 0, sortable.size()); } public static void sort(Sortable4 sortable, int start, int end) { int length = end - start; if (length < QSORT_LENGTH_THRESHOLD) { insertionSort(sortable, start, end); return; } qsort(sortable, start, end); } public static void qsort(Sortable4 sortable, int start, int end) { int length = end - start; int middle = start + length / 2; if (length > 7) { int bottom = start; int top = end - 1; if (length > 40) { length /= 8; bottom = middleValueIndex(sortable, bottom, bottom + length, bottom + (2 * length)); middle = middleValueIndex(sortable, middle - length, middle, middle + length); top = middleValueIndex(sortable, top - (2 * length), top - length, top); } middle = middleValueIndex(sortable, bottom, middle, top); } int a, b, c, d; a = b = start; c = d = end - 1; while (true) { while (b <= c && sortable.compare(b, middle) <= 0) { if (sortable.compare(b, middle) == 0) { middle = newPartionIndex(middle, a, b); swap(sortable, a++, b); } b++; } while (c >= b && sortable.compare(c, middle) >= 0) { if (sortable.compare(c, middle) == 0) { middle = newPartionIndex(middle, c, d); swap(sortable, c, d--); } c--; } if (b > c) { break; } middle = newPartionIndex(middle, b, c); swap(sortable, b++, c--); } length = Math.min(a - start,b - a); swap(sortable, start, b - length, length); length = Math.min(d - c, end - 1 - d); swap(sortable, b, end - length, length); length = b - a; if (length > 0) { sort(sortable, start, start + length); } length = d - c; if (length > 0) { sort(sortable, end - length, end); } } public static void insertionSort(Sortable4 sortable, int start, int end) { for (int i = start + 1; i < end; i++) { for (int j = i; j > start && sortable.compare(j - 1, j) > 0; j--) { swap(sortable, j - 1, j); } } } private static int newPartionIndex(int oldPartionIndex, int leftSwapIndex, int rightSwapIndex) { if(leftSwapIndex == oldPartionIndex) { return rightSwapIndex; } else if (rightSwapIndex == oldPartionIndex) { return leftSwapIndex; } return oldPartionIndex; } private static int middleValueIndex(Sortable4 sortable, int a, int b, int c) { if (sortable.compare(a, b) < 0) { if (sortable.compare(b, c) < 0) { return b; } else { if (sortable.compare(a, c) < 0) { return c; } else { return a; } } } else { if (sortable.compare(b, c) > 0) { return b; } else { if (sortable.compare(a, c) > 0) { return c; } else { return a; } } } } private static void swap(Sortable4 sortable, int left, int right) { if (left == right) { return; } sortable.swap(left, right); } private static void swap(Sortable4 sortable, int from, int to, int length) { while (length-- > 0) { swap(sortable, from++, to++); } } }