一 快排的java实现(可以参考大话数据结构里面的内容)
package ch04;
public class QuickSort {
/**
* 快排的基本思想:通过一趟排序将待排记录分割成独立的两部分
* 其中一部分的关键字比例外一部分记录的关键字要小
* 再,分别对这两部分进行排序
*
*/
public static void quickSort(int []arr, int low, int high){
if(low>high){
return;
}else{
int p=partition(arr,low,high);//将数组 分成两部分
quickSort(arr,low,p-1); //对低子表递归排序
quickSort(arr, p+1, high);//对高字表递归排序
}
}
public static int partition(int[] arr, int low, int high) {
int pivotkey;
pivotkey=arr[low];//字表的第一个记录做枢轴记录
while(low<high){//从表的两端交替向中间扫描
while(low<high && arr[high]>=pivotkey)
high--;
swap(arr,low,high); //将比pivotkey小的交换到低端
while(low<high && arr[low]<=pivotkey)
low++;
swap(arr,low,high); //将比pivotkey大的交换到高端
}
return low;
}
public static void swap(int[] arr, int low, int high) {
int temp=arr[low];
arr[low]=arr[high];
arr[high]=temp;
}
public static void main(String[] args) {
int arr[]={3,95,0,-11,7,2,6};
quickSort(arr, 0, arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
}
二 快排的优化
pivotkey=arr[low] 将导致总是固定选取 第一个关键字 ,导致性能瓶颈
(1) 通过三数取中 保证pivotkey是一个中间数,加入几行代码即可
package ch04;
public class QSort {
/**
* 快排的优化
*/
public static void quickSort(int []arr, int low, int high){
if(low>high){
return;
}else{
int p=partition(arr,low,high);
quickSort(arr,low,p-1);
quickSort(arr, p+1, high);
}
}
public static int partition(int[] arr, int low, int high) {
int pivotkey;
//
int mid=low+(high-low)/2;
if(arr[low]>arr[high]) swap(arr,low,high);
if(arr[mid]>arr[high]) swap(arr,high,mid);
if(arr[mid]>arr[low]) swap(arr,low,mid);//此时 arr[low]是左中右 三个关键字的中间值
///
pivotkey=arr[low];//字表的第一个记录做枢轴记录
while(low<high){//从表的两端交替向中间扫描
while(low<high && arr[high]>=pivotkey)
high--;
swap(arr,low,high);
while(low<high && arr[low]<=pivotkey)
low++;
swap(arr,low,high);
}
return low;
}
public static void swap(int[] arr, int low, int high) {
int temp=arr[low];
arr[low]=arr[high];
arr[high]=temp;
}
public static void main(String[] args) {
int arr[]={3,95,0,-11,7,2,6};
quickSort(arr, 0, arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
}
(2)对于较少记录的排序,用插入排序
public static void quickSort(int []arr, int low, int high){
if(high-low>7){//也有资料说取50更合理
int p=partition(arr,low,high);
quickSort(arr,low,p-1);
quickSort(arr, p+1, high);
}else{
insertSort(arr);
}
}
(3)使用尾递归优化(可以缩减堆栈深度)
quickSort(arr, p+1, high); 这句话可以用循环进行替代
最后代码如下
package ch04;
public class QSort {
/**
* 快排的优化
*/
public static void quickSort(int []arr, int low, int high){
int p;
if(high-low>7){//也有资料说取50更合理
while(low<high){
p=partition(arr,low,high);
quickSort(arr,low,p-1);
low=p+1;
}
}else{
insertSort(arr);
}
}
public static int partition(int[] arr, int low, int high) {
int pivotkey;
//
int mid=low+(high-low)/2;
if(arr[low]>arr[high]) swap(arr,low,high);
if(arr[mid]>arr[high]) swap(arr,high,mid);
if(arr[mid]>arr[low]) swap(arr,low,mid);//此时 arr[low]是左中右 三个关键字的中间值
///
pivotkey=arr[low];//字表的第一个记录做枢轴记录
while(low<high){//从表的两端交替向中间扫描
while(low<high && arr[high]>=pivotkey)
high--;
swap(arr,low,high);
while(low<high && arr[low]<=pivotkey)
low++;
swap(arr,low,high);
}
return low;
}
public static void insertSort(int []arr){
int temp=0;
for(int i=1;i<arr.length;i++){//比较length-1次
temp=arr[i];
int j=i-1;
while(j>=0 && temp<arr[j]){//如果第二个元素小于第一个元素
arr[j+1]=arr[j];//将元素往后面移动一位
j--;
}
arr[j+1]=temp;//最小的元素放到第一个位置
}
}
public static void swap(int[] arr, int low, int high) {
int temp=arr[low];
arr[low]=arr[high];
arr[high]=temp;
}
public static void main(String[] args) {
int arr[]={3,95,0,-11,7,2,6};
int arr1[]={3,95,0,-11,7,2,6,89,70,77,123,57,90};
quickSort(arr, 0, arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
quickSort(arr1, 0, arr1.length-1);
for (int i = 0; i < arr1.length; i++) {
System.out.print(arr1[i]+" ");
}
}
}