1 /*******************************************************************************
2 * Copyright 2011 See AUTHORS file.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 ******************************************************************************/
17 package com.badlogic.gdx.utils;
19 import java.util.Comparator;
23 * Implementation of Tony Hoare's quickselect algorithm.
24 * Running time is generally O(n), but worst case is O(n**2)
25 * Pivot choice is median of three method, providing better performance
26 * than a random pivot for partially sorted data.
29 public class QuickSelect<T> {
31 private Comparator<? super T> comp;
33 public int select(T[] items, Comparator<T> comp, int n, int size) {
36 return recursiveSelect(0, size - 1, n);
39 private int partition(int left, int right, int pivot) {
40 T pivotValue = array[pivot];
43 for (int i = left; i < right; i++) {
44 if (comp.compare(array[i], pivotValue) < 0) {
53 private int recursiveSelect(int left, int right, int k) {
54 if (left == right) return left;
55 int pivotIndex = medianOfThreePivot(left, right);
56 int pivotNewIndex = partition(left, right, pivotIndex);
57 int pivotDist = (pivotNewIndex - left) + 1;
60 result = pivotNewIndex;
62 else if (k < pivotDist) {
63 result = recursiveSelect(left, pivotNewIndex - 1, k);
65 result = recursiveSelect(pivotNewIndex + 1, right, k - pivotDist);
70 /** Median of Three has the potential to outperform a random pivot, especially for partially sorted arrays */
71 private int medianOfThreePivot(int leftIdx, int rightIdx) {
72 T left = array[leftIdx];
73 int midIdx = (leftIdx + rightIdx) / 2;
74 T mid = array[midIdx];
75 T right = array[rightIdx];
77 // spaghetti median of three algorithm
78 // does at most 2 comparisons
79 if (comp.compare(left, mid) > 0) {
80 if (comp.compare(mid, right) > 0) {
82 } else if (comp.compare(left, right) > 0) {
88 if (comp.compare(left, right) > 0) {
90 } else if (comp.compare(mid, right) > 0) {
98 private void swap(int left, int right) {
100 array[left] = array[right];