1、快排算法 java
/**
* quicksort to sort array
*
*/
public class QuickSort {
int partition(double a[], int low, int high) {
double tmp = a[low];
int i = low, j = high;
while (i < j) {
while (i < j && a[j] >= tmp){
j--;
}
while (i < j && a[i] <= tmp){
i++;
}
swap(a, i, j);
}
a[low] = a[i];
a[i] = tmp;
return i;
}
void swap(double a[], int i, int j) {
double tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
void quickSort(double a[], int low, int high) {
if (low < high) {
int pos = partition(a, low, high);
quickSort(a, low, pos - 1);
quickSort(a, pos + 1, high);
}
}
public static void main(String[] args) {
QuickSort test = new QuickSort();
double a[] = {1d, 10d, 7d,9d,11d,1d,50d,3d};
test.quickSort(a, 0, a.length - 1);
System.out.println(a);
}
}
2、求中位数算法
/**
* 快排找中位数
* 思想:转化成找第K小的数 k = array.length / 2 + 1
* partition分成两边后
* 1、左边个数>K,则继续在左边找
* 2、左边个数<K,则在右边找,此时newK = oldK - 左边个数
* 3、当相等时,则partition得到的pos即是中位数,这种情况分成奇偶两种情况
* a、奇数时直接返回
* b、偶数时要找到该中位数左边区域的最大值
* 最大值分两种情况:
* 1、该中位数所在迭代中左边还有数,则取左边的最大值
* 2、该中位数所在迭代中左边无值,则取上回分裂中将该中位数分到右边的分裂点,即程序中的prePart
*
*/
public class QuieckSortMedium {
private boolean bOdd;//是否奇偶数
private int kv;//k值
private double medium;
int partition(double a[], int low, int high) {
double tmp = a[low];
int i = low, j = high;
while (i < j) {
while (i < j && a[j] >= tmp){
j--;
}
while (i < j && a[i] <= tmp){
i++;
}
swap(a, i, j);
}
a[low] = a[i];
a[i] = tmp;
return i;
}
void swap(double a[], int i, int j) {
if(i == j){
return;
}
double tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
void findMedium(double a[]){
bOdd = a.length % 2 == 0;
kv = a.length / 2 + 1;
medium = 0;
findK(a, 0, a.length - 1, kv, -1);
}
/**
* 需求第K小
* @param a
* @param low
* @param high
* @param k
* @param prePart 上回分裂中将该中位数分到右边的分裂点
*/
void findK(double a[], int low, int high, int k, int prePart){
if(low > high){
return;
}
int pos = partition(a, low, high);
int left = pos - low + 1;//左边个数
if(k > left){//中位数在分裂点右边,将该分裂点作为下次迭代的prePart
findK(a, pos + 1, high, k - left, pos);
}
else if(k < left){//中位数在分裂点左边,本次的prePart作为下次迭代的prePart
findK(a, low, pos - 1, k, prePart);
}
else{
if(bOdd){//偶数时的中位数处理,取两个中位数的均值
double v1 = a[pos];
double v2 = 0;
if(low >= pos){
v2 = a[prePart]; //左边无值时取prePart
}else{
v2 = findMax(a, low, pos - 1);//左边有值时取左边最大值
}
medium = (v1 + v2) / 2;
}else{
medium = a[pos];
}
}
}
double findMax(double a[], int low, int high){
double max = a[low];
for(int i = low + 1; i <= high; i ++){
if(a[i] > max){
max = a[i];
}
}
return max;
}
double getMedium(){
return medium;
}
}
3、扩展成求Java的任意对象数组的中位数
import java.util.ArrayList;
import java.util.List;
/**
* 找中位数,使用快排找第K小数算法
* @author wangzejie
*
* @param <T>
*/
public class MediumFinder<T extends Comparable<T>> {
private boolean bOdd;//是否奇偶数
private int kv;//第几大的值
private List<T> medium = new ArrayList<T>();//中位数数组
/**
* 一次quicksort划分两边
* @param a
* @param low
* @param high
* @return
*/
private int partition(T a[], int low, int high) {
T tmp = a[low];
int i = low, j = high;
while (i < j) {
while (i < j && a[j].compareTo(tmp) >= 0){
j--;
}
while (i < j && a[i].compareTo(tmp) <= 0){
i++;
}
swap(a, i, j);
}
a[low] = a[i];
a[i] = tmp;
return i;
}
/**
* 交换数组两个位置的值
* @param a
* @param i
* @param j
*/
private void swap(T a[], int i, int j) {
if(i == j){
return;
}
T tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
/**
* 需求中位值
* @param a
* @return 返回中位的T对象,当偶数时返回两点,奇数时返回一点
*/
public List<T> findMedium(T a[]){
medium.clear();
if(a.length == 1){
medium.add(a[0]);
}else if(a.length == 2){
medium.add(a[0]);
medium.add(a[1]);
}else{
bOdd = a.length % 2 == 0;
kv = a.length / 2 + 1;
findK(a, 0, a.length - 1, kv, -1);
}
return medium;
}
/**
* 寻找第K少的值
* @param a
* @param low
* @param high
* @param k
* @param prePart
*/
private void findK(T a[], int low, int high, int k, int prePart){
if(low > high){
return;
}
int pos = partition(a, low, high);
int left = pos - low + 1;
if(k > left){
findK(a, pos + 1, high, k - left, pos);
}
else if(k < left){
findK(a, low, pos - 1, k, prePart);
}
else{
if(bOdd){
T v1 = a[pos];
T v2 = null;
if(low >= pos){
v2 = a[prePart];
}else{
v2 = findMax(a, low, pos - 1);
}
medium.add(v1);
medium.add(v2);
}else{
medium.add(a[pos]);
}
}
}
/**
* 寻找数组一定范围内的最大值
* @param a
* @param low
* @param high
* @return
*/
private T findMax(T a[], int low, int high){
T max = a[low];
for(int i = low + 1; i <= high; i ++){
if(a[i].compareTo(max) > 0){
max = a[i];
}
}
return max;
}
}
public class Point implements Comparable<Point> {
private double lng;
private double lat;
private double value;
public double getLng() {
return lng;
}
public void setLng(double lng) {
this.lng = lng;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
@Override
public int compareTo(Point o) {
double t = this.value - o.value;
if (t > 0) {
return 1;
} else if (t < 0) {
return -1;
}
return 0;
}
}