您的位置:首页 > 其它

快速排序的改进

2017-10-25 12:37 267 查看
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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: