빠른 정렬
퀵의 용도 정렬 알고리즘 효율성을 정렬 높은이다 분할 컨커 주로 별개의 두 부분으로 나누어 상기 로우 트립 레코드가 정렬 될 것으로 생각된다 처리 정렬 순서 정렬 파티션, 키워드 부분보다 작고, 큰 후방 부보다 키워드 후 정렬 방식이 각각의 두 전방 및 후방 부분의 재귀 계산은 결국 전체 순서를 지시.
핵심 아이디어
빠른 정렬 (영어 : 퀵)도 교환 정렬 분할 (파티션 교환 정렬), 데이터를 주문에 의해 여행으로 알려져 별도의 두 부분으로 분류 할 경우, 모든 데이터의 다른 부분보다 모든 데이터의 한 부분이 작게하기 그리고 이 메소드 개의 부품의 정렬 빠르게 데이터 인 전체 정렬 처리는 순서가 시퀀스로 모든 데이터를 얻기 위해, 반복적 일 수있다.
코드 개발
아이디어의 실현
Step 1-从数组中挑选一个元素作为基准值(从左边和右边开始都可以)
Step 2-将两个变量分别指向数组的左侧和右侧(不包括基准值)
Step 3-左指向低索引
Step 4-右指向高索引
Step 5-比基准值小的放置在基准值前面
Step 6-比基准值大的放置在基准值后面(相同数据可以放置任意一边)
Step 7-递归(其中包括确定新的基准值)把小于基准值元素的子数列和大于基准值元素的子数列排序
의사 코드
package com.paal.demo.c01SortingBasic;
import com.paal.demo.Sort;
import com.paal.demo.utils.SortTestHelper;
/**
* <p/>
* <li>title: 快速排序-基础版</li>
* <li>@author: li.pan</li>
* <li>Date: 2019/12/10 22:50 下午</li>
* <li>Version: V1.0</li>
* <li>Description: todo</li>
*/
public class QuickSort implements Sort {
/**
* 快速排序入口
*
* @param arr 数组
*/
@Override
public void sort(Integer[] arr) {
int n = arr.length;
sort(arr, 0, n - 1);
}
/**
* 递归使用快速排序,对arr[l...r]的范围进行排序
*
* @param arr 无序集合
* @param l 低索引
* @param r 高索引
*/
public static void sort(Integer[] arr, int l, int r) {
// 递归到底
if (l >= r)
return;
int p = partition(arr, l, r);
sort(arr, l, p - 1);
sort(arr, p + 1, r);
}
/**
* 比基准值小的放置在基准值前面,比基准值大的放置在基准值后面(相同数据可以放置任意一边)
* 返回p, 使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p]
*
* @param arr 无序数组
* @param l 低索引
* @param r 高索引
* @return
*/
private static int partition(Integer[] arr, int l, int r) {
Integer v = arr[l];
int j = l; // arr[l+1...j] < v ; arr[j+1...i) > v
for (int i = l + 1; i <= r; i++)
if (arr[i] < v) {
j++;
SortTestHelper.swap(arr, j, i);
}
SortTestHelper.swap(arr, l, j);
return j;
}
}
/**
* 快速排序测试方法
*/
@Test
public void quickSortTest() {
Integer[] integers0 = SortTestHelper.generateRandomArray(100, 0, 1000000);
Integer[] integers1 = SortTestHelper.generateRandomArray(10000, 0, 1000000);
Integer[] integers2 = SortTestHelper.generateRandomArray(100000, 0, 1000000);
System.out.println("------------------------------随机数组--------------------------------");
System.out.println("插入排序测试1数据量为100" + SortTestHelper.testSort(integers0, new InsertionSort()));
System.out.println("插入排序测试2数据量为10000" + SortTestHelper.testSort(integers1, new InsertionSort()));
System.out.println("插入排序测试3数据量为100000" + SortTestHelper.testSort(integers2, new InsertionSort()));
System.out.println("归并排序优化测试1数据量为100" + SortTestHelper.testSort(integers0, new MergeSortOptimize()));
System.out.println("归并排序优化测试2数据量为10000" + SortTestHelper.testSort(integers1, new MergeSortOptimize()));
System.out.println("归并排序优化测试3数据量为100000" + SortTestHelper.testSort(integers2, new MergeSortOptimize()));
System.out.println("快速排序测试1数据量为100" + SortTestHelper.testSort(integers0, new QuickSort()));
System.out.println("快速排序测试2数据量为10000" + SortTestHelper.testSort(integers1, new QuickSort()));
System.out.println("快速排序测试3数据量为100000" + SortTestHelper.testSort(integers2, new QuickSort()));
}
결과
------------------------------随机数组--------------------------------
插入排序测试1数据量为100排序时长为: 0.005s
插入排序测试2数据量为10000排序时长为: 0.089s
插入排序测试3数据量为100000排序时长为: 5.728s
归并排序优化测试1数据量为100排序时长为: 0.0s
归并排序优化测试2数据量为10000排序时长为: 0.001s
归并排序优化测试3数据量为100000排序时长为: 0.005s
快速排序测试1数据量为100排序时长为: 0.0s
快速排序测试2数据量为10000排序时长为: 0.046s
快速排序测试3数据量为100000排序时长为: 6.721s
코드 최적화
-
(A)의 최적화 : 삽입 정렬하지만, 더 빠른 성능을 사용하여 배열 데이터의 소량의 바닥층은 작을 때 데이터의 양, 대안 빠른 삽입 정렬 파티션 순서 사용
-
최적화 II : 우리는 큐 요소의 모든 머리를 취할 수 있도록 배열이 거의 배열을 정렬 할 수 있기 때문에, 당신은 임의의 요소를 가지고가는 시간이 걸릴 수 있습니다
-
세 (최적화 빠르게 행 삼방 ), V와 동일한 반복 많은 요소에 대한 어레이, 우리는 단지 어레이의 일부분이 될 수는 2 분할되어 있지만,보다 작 V의 배열로 분할 될 수 있고, V는 이하보다 세 부분이며 정렬의 두 부분이 반복적으로 수행되는 것보다 V 및 V가 큰
의사 코드
package com.paal.demo.c01SortingBasic.optimize;
import com.paal.demo.Sort;
import com.paal.demo.utils.SortTestHelper;
/**
* <p/>
* <li>title: 快速排序优化</li>
* <li>@author: li.pan</li>
* <li>Date: 2019/12/10 22:50 下午</li>
* <li>Version: V1.0</li>
* <li>Description:
* 优化1: 对于小规模数组, 使用插入排序,效率更佳
* 优化2: 对于arr[l...r]可能近乎有序的数组,采用获取随机值的方式随机获取基准值位置
* 优化3: 对于arr[l...r]可能存在大量元素的数组,可以将数组分割为小于V,等于V,大于V的三部分,然后对小于V和大于V部分进行递归
* </li>
*/
public class QuickSortOptimize implements Sort {
/**
* 快速排序入口
*
* @param arr 数组
*/
@Override
public void sort(Integer[] arr) {
int n = arr.length;
sort(arr, 0, n - 1);
}
/**
* 递归使用快速排序,对arr[l...r]的范围进行排序
*
* @param arr 无序集合
* @param l 低索引
* @param r 高索引
*/
private static void sort(Integer[] arr, int l, int r) {
/**
* 优化1: 对于小规模数组, 使用插入排序,效率更佳
*/
if (r - l <= 15) {
insertionSort(arr, l, r);
return;
}
/**
* 优化2: 对于arr[l...r]可能近乎有序的数组,采用获取随机值的方式随机获取基准值位置
* (int) (Math.random() * (r - l + 1)) + l
*/
SortTestHelper.swap(arr, l, (int) (Math.random() * (r - l + 1)) + l);
Integer v = arr[l];
/**
* 优化3: 对于arr[l...r]可能存在大量元素的数组,可以将数组分割为小于V,等于V,大于V的三部分,然后对小于V和大于V部分进行递归
* 简称"三路快排"
*/
int lt = l; // arr[l+1...lt] < v
int gt = r + 1; // arr[gt...r] > v
int i = l + 1; // arr[lt+1...i) == v
while (i < gt) {
if (arr[i] < v) {
SortTestHelper.swap(arr, i, lt + 1);
i++;
lt++;
} else if (arr[i].compareTo(v) > 0) {
SortTestHelper.swap(arr, i, gt - 1);
gt--;
} else { // arr[i] == v
i++;
}
}
SortTestHelper.swap(arr, l, lt);
sort(arr, l, lt - 1);
sort(arr, gt, r);
}
// 对arr[l...r]的区间使用InsertionSort排序
public static void insertionSort(Integer[] arr, int l, int r) {
for (int i = l + 1; i <= r; i++) {
Integer e = arr[i];
int j = i;
for (; j > l && arr[j - 1] > e; j--)
arr[j] = arr[j - 1];
arr[j] = e;
}
}
}
/**
* 快速排序测试优化方法
*/
@Test
public void quickOptimizeSortTest() {
Integer[] integers0 = SortTestHelper.generateRandomArray(100, 0, 1000000);
Integer[] integers1 = SortTestHelper.generateRandomArray(10000, 0, 1000000);
Integer[] integers2 = SortTestHelper.generateRandomArray(100000, 0, 1000000);
System.out.println("------------------------------随机数组--------------------------------");
System.out.println("插入排序测试1数据量为100" + SortTestHelper.testSort(integers0, new InsertionSort()));
System.out.println("插入排序测试2数据量为10000" + SortTestHelper.testSort(integers1, new InsertionSort()));
System.out.println("插入排序测试3数据量为100000" + SortTestHelper.testSort(integers2, new InsertionSort()));
System.out.println("归并排序优化测试1数据量为100" + SortTestHelper.testSort(integers0, new MergeSortOptimize()));
System.out.println("归并排序优化测试2数据量为10000" + SortTestHelper.testSort(integers1, new MergeSortOptimize()));
System.out.println("归并排序优化测试3数据量为100000" + SortTestHelper.testSort(integers2, new MergeSortOptimize()));
System.out.println("快速排序测试1数据量为100" + SortTestHelper.testSort(integers0, new QuickSort()));
System.out.println("快速排序测试2数据量为10000" + SortTestHelper.testSort(integers1, new QuickSort()));
System.out.println("快速排序测试3数据量为100000" + SortTestHelper.testSort(integers2, new QuickSort()));
System.out.println("快速排序测试1数据量为100" + SortTestHelper.testSort(integers0, new QuickSortOptimize()));
System.out.println("快速排序测试2数据量为10000" + SortTestHelper.testSort(integers1, new QuickSortOptimize()));
System.out.println("快速排序测试3数据量为100000" + SortTestHelper.testSort(integers2, new QuickSortOptimize()));
System.out.println("------------------------------近乎有序的数组--------------------------------");
Integer[] integers00 = SortTestHelper.generateNearlyOrderedArray(100, 10);
Integer[] integers11 = SortTestHelper.generateNearlyOrderedArray(10000, 100);
Integer[] integers22 = SortTestHelper.generateNearlyOrderedArray(100000, 1000);
System.out.println("插入排序测试1数据量为100" + SortTestHelper.testSort(integers00, new InsertionSort()));
System.out.println("插入排序测试2数据量为10000" + SortTestHelper.testSort(integers11, new InsertionSort()));
System.out.println("插入排序测试3数据量为100000" + SortTestHelper.testSort(integers22, new InsertionSort()));
System.out.println("归并排序优化测试1数据量为100" + SortTestHelper.testSort(integers00, new MergeSortOptimize()));
System.out.println("归并排序优化测试2数据量为10000" + SortTestHelper.testSort(integers11, new MergeSortOptimize()));
System.out.println("归并排序优化测试3数据量为100000" + SortTestHelper.testSort(integers22, new MergeSortOptimize()));
System.out.println("快速排序测试1数据量为100" + SortTestHelper.testSort(integers00, new QuickSort()));
System.out.println("快速排序测试2数据量为10000" + SortTestHelper.testSort(integers11, new QuickSort()));
System.out.println("快速排序测试3数据量为100000" + SortTestHelper.testSort(integers22, new QuickSort()));
System.out.println("快速排序测试1数据量为100" + SortTestHelper.testSort(integers00, new QuickSortOptimize()));
System.out.println("快速排序测试2数据量为10000" + SortTestHelper.testSort(integers11, new QuickSortOptimize()));
System.out.println("快速排序测试3数据量为100000" + SortTestHelper.testSort(integers22, new QuickSortOptimize()));
Integer[] integers000 = SortTestHelper.generateRandomArray(100, 0, 10);
Integer[] integers111 = SortTestHelper.generateRandomArray(10000, 0, 100);
Integer[] integers222 = SortTestHelper.generateRandomArray(100000, 0, 1000);
System.out.println("------------------------------大量重复的数组--------------------------------");
System.out.println("插入排序测试1数据量为100" + SortTestHelper.testSort(integers000, new InsertionSort()));
System.out.println("插入排序测试2数据量为10000" + SortTestHelper.testSort(integers111, new InsertionSort()));
System.out.println("插入排序测试3数据量为100000" + SortTestHelper.testSort(integers222, new InsertionSort()));
System.out.println("归并排序优化测试1数据量为100" + SortTestHelper.testSort(integers000, new MergeSortOptimize()));
System.out.println("归并排序优化测试2数据量为10000" + SortTestHelper.testSort(integers111, new MergeSortOptimize()));
System.out.println("归并排序优化测试3数据量为100000" + SortTestHelper.testSort(integers222, new MergeSortOptimize()));
System.out.println("快速排序测试1数据量为100" + SortTestHelper.testSort(integers000, new QuickSort()));
System.out.println("快速排序测试2数据量为10000" + SortTestHelper.testSort(integers111, new QuickSort()));
System.out.println("快速排序测试3数据量为100000" + SortTestHelper.testSort(integers222, new QuickSort()));
System.out.println("快速排序测试1数据量为100" + SortTestHelper.testSort(integers000, new QuickSortOptimize()));
System.out.println("快速排序测试2数据量为10000" + SortTestHelper.testSort(integers111, new QuickSortOptimize()));
System.out.println("快速排序测试3数据量为100000" + SortTestHelper.testSort(integers222, new QuickSortOptimize()));
}
결과
------------------------------随机数组--------------------------------
插入排序测试1数据量为100排序时长为: 0.001s
插入排序测试2数据量为10000排序时长为: 0.08s
插入排序测试3数据量为100000排序时长为: 5.66s
归并排序优化测试1数据量为100排序时长为: 0.0s
归并排序优化测试2数据量为10000排序时长为: 0.005s
归并排序优化测试3数据量为100000排序时长为: 0.003s
快速排序测试1数据量为100排序时长为: 0.0s
快速排序测试2数据量为10000排序时长为: 0.045s
快速排序测试3数据量为100000排序时长为: 6.748s
快速排序测试1数据量为100排序时长为: 0.0s
快速排序测试2数据量为10000排序时长为: 0.004s
快速排序测试3数据量为100000排序时长为: 0.033s
------------------------------近乎有序的数组--------------------------------
插入排序测试1数据量为100排序时长为: 0.0s
插入排序测试2数据量为10000排序时长为: 0.001s
插入排序测试3数据量为100000排序时长为: 0.097s
归并排序优化测试1数据量为100排序时长为: 0.0s
归并排序优化测试2数据量为10000排序时长为: 0.0s
归并排序优化测试3数据量为100000排序时长为: 0.0s
快速排序测试1数据量为100排序时长为: 0.0s
快速排序测试2数据量为10000排序时长为: 0.031s
快速排序测试3数据量为100000排序时长为: 3.459s
快速排序测试1数据量为100排序时长为: 0.0s
快速排序测试2数据量为10000排序时长为: 0.0s
快速排序测试3数据量为100000排序时长为: 0.008s
------------------------------大量重复的数组--------------------------------
插入排序测试1数据量为100排序时长为: 0.0s
插入排序测试2数据量为10000排序时长为: 0.039s
插入排序测试3数据量为100000排序时长为: 5.454s
归并排序优化测试1数据量为100排序时长为: 0.0s
归并排序优化测试2数据量为10000排序时长为: 0.0s
归并排序优化测试3数据量为100000排序时长为: 0.0s
快速排序测试1数据量为100排序时长为: 0.0s
快速排序测试2数据量为10000排序时长为: 0.034s
快速排序测试3数据量为100000排序时长为: 7.021s
快速排序测试1数据量为100排序时长为: 0.0s
快速排序测试2数据量为10000排序时长为: 0.001s
快速排序测试3数据量为100000排序时长为: 0.005s