package com.txq.test;
/*** quicksort,三方面改进:①三数中值选择枢纽元②容量小的时候使用插入排序③重复元素的处理* @author XueQiang Tong* @date 2017/10/25*/
public class QS {public void quicksort(int []arr,int low,int high){int first = low;int last = high;int left = low;int right = high;int leftLen = 0;int rightLen = 0;//当分割后的容量较小时,使用插入排序,提高性能if(high - low + 1 <= 10){InsertSort(arr,low,high);return;}int key = SelectPivotMedianOfThree(arr,low,high);while(low < high){while(high > low && arr[high] >= key){if(arr[high] == key){//重复元素处理策略:分割过程中把他们放在数组两端,递归调用时掠过他们,提高性能swap(arr,high,right);right --;rightLen ++;}high --;}arr[low] = arr[high];//交换while(high > low && arr[low] <= key){if(arr[low] == key){swap(arr,low,left);left ++;leftLen ++;}low ++;}arr[high] = arr[low];//交换}arr[low] = key;//此时总是low = high,把key放在此位置,一次迭代完成,进入下次递归调用//接下来,把重复元素存储到key的周围int i = low - 1;int j = first;while(j < left && arr[i] != key){swap(arr,j,i);i --;j ++;}i = low + 1;j = last;while(j > right && arr[i] != key){swap(arr,j,i);i ++;j --;}quicksort(arr,first,low - leftLen - 1);quicksort(arr,low + rightLen + 1,last);}/*** low,mid,high,对三个数排序,arr[mid] <= arr[low] <= arr[high],取arr[low]作为枢纽元* @param arr* @param low* @param high* @return*/private int SelectPivotMedianOfThree(int[] arr, int low, int high) {int mid = low + ((high - low) >> 1);if(arr[mid] > arr[high]){swap(arr,mid,high);}if(arr[low] > arr[high]){swap(arr,low,high);}if(arr[low] < arr[mid]){swap(arr,low,mid);}return arr[low];}public void swap(int arr[],int i, int j) {int tmp;tmp = arr[i];arr[i] = arr[j];arr[j] = tmp; }/*** 插入排序* @param arr*/private void InsertSort(int[] arr,int low,int high) {int i,j;int n = high - low + 1;int target;for(i = low+1;i < low+n;i++){j = i;target = arr[i];while(j > low && target < arr[j-1]){arr[j] = arr[j-1];j--;}arr[j] = target;} }
}