텐 고전적인 정렬 알고리즘!
머리말
제발확인이것 좀 봐 : 정렬 알고리즘은 + 코드 환경 준비 - 지식 사전 .
위의 내용이 준비가되면,의 신속 종류의를 시작하자!
빠른 정렬
구현 과정 :
- ①에서 시퀀스를 선택 피벗 포인트 소자 (피벗)
소자 지점의 축선의 각각의 선택 엘리먼트 0의 위치를 가정 - ② 피벗 (2)의 서브 시퀀스로 분할
피벗 요소 (왼쪽) 전면에 피봇보다 작은
백 피봇 요동 소자 (우측)보다 클 것이다
방전 소자 측 캔 피봇 등전위 - ① ② ③ 서브 동작 시퀀스
없이 재분할 (시퀀스에서 단지 하나 개의 요소)까지
빠른 정렬의 본질은 그림 쇼 :
- 각 요소는 점진적으로 피봇 포인트 요소로 변환 될
구성 피벗 포인트
. (6) 시퀀스 {들어 . 8 . 8 B 2 ,. 6 B ., 4 ,. 9 ,. 5 ,. 7} 구성된 축점 :
- 첫째로 백업 엘리먼트 0의 위치, 피벗 포인트 소자 ;
- 궁극적 인 목적은 구성하는 중심 요소 서열로 피봇 점 :
좌측 절반은 이하 피벗 점 요소 이외 의 서열 ;
우측은 피벗 지점 소자 초과 의 서열 ,
다음과 같다 :
어떻게 당신이 그것을 구조화합니까?
제 위치 시퀀스 시작
- 덜 축 요소보다 사이트 요소를 찾고, 오른쪽에서 왼쪽으로 스캔
나중에 발견 , 위치로 시작, 시작 ++, 다음 찾을 역 ; - 축 부재보다 큰 점 요소를 찾고, 왼쪽에서 오른쪽으로 스캔,
뒷부분의 최종 위치로, 최종하고 찾을 역방향 ; - 좌우 한 다음, 위에 설명되어 스캔하면 == 단부 시작 백업 개시 중앙으로 소자의 피벗 점 .
이 과정은 조금 때까지, 나중에 찾을 왼쪽에서 오른쪽으로 왼쪽으로 오른쪽 볼 필요가, 프로세스의주기를 혼란 요소의 왼쪽 절반에 피벗 포인트보다 작은 모든 요소 , 피벗 포인트 이상의 모든 요소보다 큰 요소의 오른쪽 절반으로 피벗 점의 완전한 건설.
구성 피벗 포인트 -에 대한 코드
어떻게 코드를 구현하는 바로 스캔 왼쪽에서 와 왼쪽 스캔 오른쪽에서 교류 그것? 코드를 살펴는 이유를 이해할 수있을 것이다. . .
/**
* 构造出 [begin, end) 范围的轴点元素
* @return 轴点元素的最终位置
*/
private int pivotIndex(int begin, int end){
// 备份begin位置的元素
T pivot = array[begin];
// end指向最后一个元素
end--;
while(begin < end){
while(begin < end){ // 从右往左扫描
if(cmp(pivot, array[end]) < 0){ // 右边元素 > 轴点元素
end--;
}else{ // 右边元素 <= 轴点元素
array[begin++] = array[end];
break;
}
}
while(begin < end){ // 从左往右扫描
if(cmp(pivot, array[begin]) > 0){ // 左边元素 < 轴点元素
begin++;
}else{ // 左边元素 >= 轴点元素
array[end--] = array[begin];
break;
}
}
}
// 将轴点元素放入最终的位置
array[begin] = pivot;
// 返回轴点元素的位置
return begin; // begin==end
}
구성 피벗 포인트 - 최적화
균일 피벗 점뿐만 아니라, 주위의 요소의 수를 비교하면 가장 경우 :
- T (N) = 2 * T (N / 2) + O (N) = O (nlogn)
피벗 점 주위의 요소의 수는 매우 고르지 않은 경우, 최악의 경우 :
- T (N) = t (N - 1) + O (N) = O (N 2 )
접근 방식은 일반적으로 촬영되는 최악의 경우의 확률을 줄이기 위해 :
- 임의로 선택된 피벗 포인트 소자
피벗 점 요소 이전에 백업 될 수 있고, 임의의 요소들의 시퀀스의 요소는 교환 위치로 시작한다.
// 随机选择轴点元素, 将 begin 位置的元素与序列中的随机元素交换一下
swap(begin, begin + (int)Math.random()*(end - begin));
// 备份begin位置的元素
T pivot = array[begin];
.....
생각? 피벗 포인트 소자 같
시퀀스의 모든 요소가 피벗 점의 요소와 동일한 경우 , 상기 알고리즘을 이용하여 , 상기 샤프트 부재는 두 개의 서브 시퀀스로 균일 점 열 수있다
생각 : 위의 코드, 판사의 CMP 위치는 어떤 영향을 할 것이다 ≥, ≤ 바뀌었다?
결과 :
- 시퀀스 피벗 포인트 요소는 매우 불균등 분할
- 시간 복잡도 O에서 최악의 결과 (N- 2 )
퀵 전체 코드
/**
* 快速排序
*/
public class QuickSort<T extends Comparable<T>> extends Sort<T> {
@Override
protected void sort() {
sort(0, array.length);
}
/**
* 对 [begin, end) 范围的元素进行快速排序
*/
private void sort(int begin, int end){
if(end - begin < 2) return;
// 确定轴点位置 O(n)
int mid = pivotIndex(begin, end);
// 对子序列进行快速排序
sort(begin, mid);
sort(mid + 1, end);
}
/**
* 构造出 [begin, end) 范围的轴点元素
* @return 轴点元素的最终位置
*/
private int pivotIndex(int begin, int end){
// 随机选择轴点元素
swap(begin, begin + (int)Math.random()*(end - begin));
// 备份begin位置的元素
T pivot = array[begin];
// end指向最后一个元素
end--;
while(begin < end){
while(begin < end){ // 从右往左扫描
if(cmp(pivot, array[end]) < 0){ // 右边元素 > 轴点元素
end--;
}else{ // 右边元素 <= 轴点元素
array[begin++] = array[end];
break;
}
}
while(begin < end){ // 从左往右扫描
if(cmp(pivot, array[begin]) > 0){ // 左边元素 < 轴点元素
begin++;
}else{ // 左边元素 >= 轴点元素
array[end--] = array[begin];
break;
}
}
}
// 将轴点元素放入最终的位置
array[begin] = pivot;
// 返回轴点元素的位置
return begin; // begin==end
}
}
20000 값은 [1, 10000] 난수 생성 분류된다 :
복잡성과 안정성
복잡성 및 빠른 정렬의 안정성 :
- 바람직하게는, 평균 시간 복잡도 : O (nlogn)
- 최악의 시간 복잡도 : O (N- 2 )
- 의 때문에 재귀 이유는 호출, 공간 복잡도 : O (logn)
- 에 속하는 불안정 정렬