일반적인 빠른 정렬
기본 값 기반을 찾은 다음베이스 왼쪽의 숫자가베이스보다 작고베이스 오른쪽의 숫자가베이스보다 크지 않도록 한 번의 여행으로 정렬하십시오. 그런 다음 두 개의 서브 어레이 정렬로 나누어줍니다. 이렇게 재귀 적.
공개 클래스 QuickSort {public static <t는 비슷한 <? super t >> void sort (t [] arr) {sort (arr, 0, arr.length -1);} public static <t는 비슷한 <? super t >> void sort (t [] arr, int left, int right) {if (왼쪽> = 오른쪽) 반환; int p = 파티션 (arr, 왼쪽, 오른쪽); sort (arr, 왼쪽, p -1); sort (arr, p + 1, 오른쪽);} private static <t extends 비슷한 <? super t >> int 파티션 (t [] arr, int left, int right) {t base = arr [left]; int j = left; for (int i = 왼쪽+1; i <= 오른쪽; i ++) {if (base.compareto (arr [i])> 0) {j ++; swap (arr, j, i);} swap (j); 정렬} public static void swap (object [] arr, int i, int j) {if (i! = j) {object temp = arr [i]; arr [i] = arr [j]; arr [j] = temp;}} private static void printarr (object [] are) {for (object o : arr) {System.out.print (o); System.out.print ( "/t");} system.out.println ();} public static void main (String args []) {integer [] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6}; printarr (// 3 5 1 7 2 9 8 4 4 4 9 9 9 9 9 9 8 6SORT (ARR); printarr (arr); // 0 1 2 3 4 5 6 7 8 9}}}빠른 정렬 최적화 : 기본 값 기반을 무작위로 선택하십시오
배열이 거의 주문되면, 빠른 주문 성능이 좋지 않습니다 (각 순서 후에는 왼쪽 및 오른쪽 서브의 재귀 크기가 매우 다르고 더 큰 부분은 결국 O (n^2)에 도달 할 수 있기 때문입니다.
솔루션 : 참조 값은 매번 첫 번째 숫자를 취하지 않고 무작위로 선택됩니다. 이것은 "거의 주문한 배열"에 의해 방해받지 않습니다. 그러나 "거의 외부 배열"의 분류 성능은 약간 떨어질 수 있습니다. 적어도 정렬 전에 교환되는 부분이 더 많습니다. 이 교환은 무의미한 점에서 의미가 없습니다 ... 많은 "운"구성 요소가 있습니다 ...
공개 클래스 QuickSort {public static <t는 비슷한 <? super t >> void sort (t [] arr) {sort (arr, 0, arr.length -1);} public static <t는 비슷한 <? super t >> void sort (t [] arr, int left, int right) {if (왼쪽> = 오른쪽) 반환; int p = 파티션 (arr, 왼쪽, 오른쪽); sort (arr, 왼쪽, p -1); sort (arr, p + 1, 오른쪽);} private static <t extends 비슷한 <? super t >> int partition (t [] arr, int left, int right) {// 정렬하기 전에 참조 값을 임의의 숫자로 교환하게하십시오. 이런 식으로, 참조 값은 무작위입니다. // 배열이 비교적 순서가 상대적으로 순서가 될 때 왼쪽과 오른쪽의 재귀 스케일이 일관되지 않아서 최악의 시간 복잡성 스왑 (arr, left, (int) (int)*(오른쪽 - 왼쪽+1)+왼쪽); t base = arr = arr [left]; int j = 왼쪽; (int i = int+1; 오른쪽 <= i ++) (base.compareto (arr [i])> 0) {j ++; swap (arr, j, i);}} swap (arr, left, j); return j; return j; // 거짓말 정렬 후 참조 값의 하단 모서리를 반환} public static void swap (object [] arr, int i, int j) {[i! = j) {[i]]; temp;}} private static void printarr (object [] arr) {for (object o : arr) {system.out.print (o); system.out.print ( "/t");} system.out.println ();} public static void main (String args []) {intger [] ar = {3, 5, 1, 7, 2, 9, 9, 9,, 4, 6}; printarr (ARR); // 3 5 1 7 2 9 8 0 4 6SORT (ARR); printarr (ARR); // 0 1 2 3 4 5 6 7 8 9}}빠른 정렬은 계속 최적화됩니다 : 삽입 정렬을 함께 사용하십시오.
빠른 주문은 문제의 규모를 지속적으로 줄이고 하위 문제를 해결하고 지속적인 재귀가 필요합니다. 그러나 재귀는 충분히 작으며,이 불안정한 + 재귀가 계속 실행되면 효율성이 그리 좋지 않을 수 있습니다.
따라서 문제가 작고 거의 순서대로되면 삽입 분류가 잘 작동합니다. Java와 함께 제공되는 Array.sort ()에서 그러한 주석을 볼 수 있습니다. "작은 배열에 삽입 정렬 사용", "가장 작은 배열에 삽입 정렬"
공개 클래스 QuickSort {public static <t는 비슷한 <? super t >> void sort (t [] arr) {sort (arr, 0, arr.length -1, 16);}/*** @param arrray* @param 왼쪽 왼쪽 왼쪽 왼쪽 왼쪽* @param k @param k 빠른 정렬이 서브 프로 블렘 <= k의 스케일을 재귀 할 때*/public <t>/sortic <t> type to type be to type be be be be be be be be be be be be be be be be be be be be be be be be be be be be be b 비슷한 <? super t >> void sort (t [] arr, int left, int right, int k) {// 스케일 시간은 (오른쪽 -Reft <= k) {insertionsort (arr, 왼쪽, 오른쪽);} int p = 파티션 (ARR, 왼쪽, 오른쪽); 정렬 (ARR, 왼쪽, p -1, k); PROUPLE <t}; super t >> void insertionsort (t [] arr, int l, int r) {for (int i = l + 1; i <= r; i ++) {t cur = arr [i]; int j = i-1; for (; <t는 비슷한 <? super t >> int partition (t [] arr, int left, int right) {// 정렬하기 전에 참조 값을 임의의 숫자로 교환하도록하십시오. 이런 식으로, 참조 값은 무작위입니다. // 배열이 상대적으로 순서 일 때 왼쪽과 오른쪽의 재귀 스케일이 일관되지 않아서 최악의 시간 복잡성 스왑 (arr, left, (int), (int) (int) (왼쪽 + 1) + 왼쪽); t base = ARR [left]; int j = 왼쪽; (int i = let + 1; i +); i). > 0) {j ++; swap (arr, j, i);}} swap (arr, left, j); return j; return j; return reto}} 공개 정적 void 스왑 (object [] arr, int i, int j) {if (i! = j) {객체 임시 [i]; arr [j]; j]; j]; printarr (object [] arr) {for (object o : arr) {system.out.print (o); system.out.print ( "/t");} system.out.println ();} public static void main (String Args []) {integer [] arr = {3, 5, 1, 7, 2, 8, 0, 4, 6}; printar (8}; 0 4 6SORT (ARR); printarr (ARR); // 0 1 2 3 4 5 6 7 8 9}}}빠른 정렬은 계속 최적화됩니다 : 양방향 빠른 정렬
초기 정상적인 빠른 정렬에서,베이스의 왼쪽의베이스 값은베이스보다 작고 오른쪽의베이스는베이스보다 크거나 같다고합니다. 이들은베이스와 동일하게 오른쪽으로 모입니다 (또는 크기 관계가 왼쪽으로 모이는 크기를 약간 변경합니다). 어쨌든, 그것은 옆으로 모일 것입니다. 배열에서 많은 숫자가 반복되면 두 서브의 크기에 큰 차이가 발생합니다. 현재로서는 숫자를베이스의 양쪽에 동일한 숫자를 기지의 양쪽에 할당하고 싶습니다.
(참고 : 코드를 테스트 할 때 삽입 정렬의 일부를보고 아래 코드에서 보는 것이 가장 좋습니다. 그렇지 않으면 데이터 볼륨이 k = 16보다 작을 때 삽입 정렬이 수행됩니다 ...)
공개 클래스 QuickSort {public static <t는 비슷한 <? super t >> void sort (t [] arr) {sort (arr, 0, arr.length -1, 16);}/*** @param arrray* @param 왼쪽 왼쪽 왼쪽 왼쪽 왼쪽* @param k @param k 빠른 정렬이 서브 프로 블렘 <= k의 스케일을 재귀 할 때*/public <t>/sortic <t> type to type be to type be be be be be be be be be be be be be be be be be be be be be be be be be be be be be b 비슷한 <? super t >> void sort (t [] arr, int 왼쪽, int 오른쪽, int k) {// insertionsort (arr, 왼쪽, 오른쪽); // return; //} if (왼쪽> = 오른쪽) retur (int p = partition (arr, 왼쪽, 오른쪽); 정렬 (ARR, 왼쪽, p- 1, k); super t >> void insertionsort (t [] arr, int l, int r) {for (int i = l + 1; i <= r; i ++) {t cur = arr [i]; int j = i-1; for (; <t는 비슷한 <? super t >> int partition (t [] arr, int left, int right) {// 정렬하기 전에 참조 값을 임의의 숫자로 교환하도록하십시오. 이런 식으로, 참조 값은 무작위입니다. // 배열이 비교적 순서가 상대적으로 순서가 될 때 왼쪽과 오른쪽의 재귀 스케일이 일관되지 않아서 최악의 시간 복잡성 스왑 (arr, left, (int) * (오른쪽 - 왼쪽 + 1) + 왼쪽); t base = arr [왼쪽]; 왼쪽 왼쪽 중간 값은 [왼쪽 + 1] + 1] + 1 + 1] +1; // 이전 줄에 언급 된 [왼쪽+1 ......... 오른쪽] 간격의 경우, [왼쪽+1 ...... i) 왼쪽 닫힌 오른쪽 열린 간격은베이스보다 작거나 같다는 것을 의미합니다. int j = 오른쪽; // 이전 두 줄에서 언급 된 [왼쪽+1 ...... 오른쪽] 간격의 경우, j는 (j ...... 오른쪽] 왼쪽 열린 개방 및 오른쪽 닫힌 간격의 값이베이스보다 크다는 것을 의미합니다. 기본보다 작은 첫 번째 요소를 사용하고 J> = Left && arr [j] .compareto (base)> 0) j-; if (i> j) {// j = i-1으로 실제로 종료된다. 정적 void 스왑 (Object [] arr, int i, int j) {if (i! = j) {object temp = arr [i]; arr [i] = arr [j]; arr [j] = temp;}} private static void printarr (object [] arr) {for (object o : arr) {System.out.print (o); System.out.print ( "/t");} system.out.println ();} public static void main (String args []) {integer [] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6}; printarr (// 3 5 1 7 2 9 8 4 4 4 9 9 9 9 9 9 8 6SORT (ARR); printarr (arr); // 0 1 2 3 4 5 6 7 8 9}}}빠른 정렬을 계속 최적화하십시오 : 두 개의 빠른 정렬은 스왑이 필요하지 않습니다.
위의 두 경로가 기본보다 큰 값을 찾고 기본보다 적은 값을 찾으면 Swap () 메소드를 사용하여 교환합니다. 2 자리 교환에는 세 번째 변수 온도의 작동이 포함되며, 더 많은 읽기 및 쓰기 작업이 포함됩니다. 다음으로 직접 할당 방법을 사용하여 오른쪽보다 적은 것보다 왼쪽보다 큽니다. 나와 J를 만나면 그 위치는베이스를 배치 해야하는 위치입니다. 이 여행이 완료되었습니다. 그냥 되 찾으십시오.
공개 클래스 QuickSort {public static <t는 비슷한 <? super t >> void sort (t [] arr) {sort (arr, 0, arr.length -1, 16);}/*** @param arrray* @param 왼쪽 왼쪽 왼쪽 왼쪽 왼쪽* @param k @param k 빠른 정렬이 서브 프로 블렘 <= k의 스케일을 재귀 할 때*/public <t>/sortic <t> type to type be to type be be be be be be be be be be be be be be be be be be be be be be be be be be be be be b 비슷한 <? super t >> void sort (t [] arr, int 왼쪽, int 오른쪽, int k) {// insertionsort (arr, 왼쪽, 오른쪽); // return; //} if (왼쪽> = 오른쪽) retur (int p = partition (arr, 왼쪽, 오른쪽); 정렬 (ARR, 왼쪽, p- 1, k); super t >> void insertionsort (t [] arr, int l, int r) {for (int i = l + 1; i <= r; i ++) {t cur = arr [i]; int j = i-1; for (; <t는 비슷한 <? super t >> int partition (t [] arr, int left, int right) {// 정렬하기 전에 참조 값을 임의의 숫자로 교환하도록하십시오. 이런 식으로, 참조 값은 무작위입니다. // 배열이 비교적 순서가 상대적으로 순서가 될 때 왼쪽과 오른쪽의 재귀 스케일이 일관되지 않아서 최악의 시간 복잡성 스왑 (arr, left, (int) * (int) * (오른쪽-왼쪽 + 1) + 왼쪽); t base = arr [left]; // 기본 값, 왼쪽 왼쪽 왼쪽에 왼쪽 + 1 등을 봅니다. = 왼쪽; // 이전 줄에 언급 된 [왼쪽+1 ......... 오른쪽] 간격의 경우, [왼쪽+1 ...... i) 왼쪽으로 구성된 오른쪽으로 구성된 오른쪽으로 구성된 간격 값은 기본보다 작거나 같다는 것을 의미합니다. int j = 오른쪽; // 이전 두 줄에서 언급 된 [왼쪽+1 ...... 오른쪽] 간격의 경우, j는 (j ...... 오른쪽] 왼쪽-오픈 및 오른쪽 입자 간격의 값이베이스보다 크거나 같음을 의미합니다. arr [j]; // 왼쪽에서 오른쪽으로 스캔 한 다음베이스보다 큰 요소를 스캔 한 다음 (i <j && arr [i]. compareto (base) <0) i ++; arr [j] = arr [i];} j. ! = j) {object temp = arr [i]; arr [i] = arr [j]; arr [j] = temp;}} private static void printarr (object [] arr) {for (object o : arr) {system.out.print (o); system.out.print ( "/t");} system.out.println ())) {integer [] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6}; printarr (arr); // 3 5 1 7 2 9 8 0 4 6sort (ARR); printarr (ARR); // 0 1 2 3 4 5 6 7 8 9}}빠른 정렬은 계속 최적화됩니다 : 많은 양의 데이터와 많은 반복이 사용되면 3 방향 빠른 정렬을 사용하십시오.
배열을 세 가지 경로로 나눕니다. 첫 번째 경로는베이스보다 작고, 두 번째 경로는베이스와 같고, 세 번째 경로는베이스보다 큽니다.
포인터를 사용하여 다음과 같은 경우 앞뒤로 스캔하십시오.
1. CUR에 의해 가리키는 숫자는 기본보다 작습니다.
2. CUR에 의해 가리키는 숫자는 기본과 동일합니다. cur ++
3. CUR에 의해 가리키는 숫자는 기본보다 크다.
cur> j 일 때, 그것은 세 가지 경로가 모두 완료되었음을 의미합니다.
공개 클래스 QuickSort {public static <t는 비슷한 <? super t >> void sort (t [] arr) {sort (arr, 0, arr.length -1, 16);}/*** @param arrray* @param 왼쪽 왼쪽 왼쪽 왼쪽 왼쪽* @param k @param k 빠른 정렬이 서브 프로 블렘 <= k의 스케일을 재귀 할 때*/public <t>/sortic <t> type to type be to type be be be be be be be be be be be be be be be be be be be be be be be be be be be be be b 비슷한 <? super t >> void sort (t [] arr, int left, int right, int k) {// insertionsort (arr, 왼쪽, 오른쪽); // return; //} if (왼쪽> = 오른쪽) retur; int [] ret = partition (arr, 왼쪽, 오른쪽); 정렬 (왼쪽, ret, ret [1], k);} publatic <? super t >> void insertionsort (t [] arr, int l, int r) {for (int i = l + 1; i <= r; i ++) {t cur = arr [i]; int j = i-1; for (; 정렬 할 @param arr 배열* @param 배열의 왼쪽 경계를 정렬 할 왼쪽* @param 오른쪽 배열의 오른쪽 경계* @param <t> generics* @return*/private static <t는 비슷한 <? super t >> int [] partition (t [] arr, int left, int right) {// 정렬하기 전에 참조 값을 임의의 숫자로 교환하게하십시오. 이런 식으로, 참조 값은 무작위입니다. // 배열이 비교적 순서 일 때 왼쪽과 오른쪽의 재귀 적 스케일이 일관되지 않아서 최악의 시간 복잡성 스왑 (arr, 왼쪽, (int), (int) (int) (int) (int), (int) (int), (int), (int) (왼쪽]; 행은 다음 3 개의 채널 (간격) int i = 왼쪽으로 나뉘어져 있습니다. // 왼쪽은 [lleft ... 왼쪽) 왼쪽 닫힌 오른쪽 열린 간격의 숫자가 기본 in j = 오른쪽보다 작음을 나타냅니다. (cur <= j) {if (arr [cur] .compareto (base) == 0) {cur ++;} else if (arr [cur] .compareto (base) <0) {swap (arr, cur ++, i ++);} else {swap (arr, cur, j-);}} new int [] {i-j+1}; 그리고 하위 프로젝트는 i 및 j}의 왼쪽과 오른쪽을 풀면 public static void swap (object [] arr, int i, int j) {if (i! = j) {객체 temp = arr [i]; arr [j]; {System.out.print (o); System.out.print ( "/t");} system.out.println ();} public static void main (String args []) {integer [] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6}; printarr (// 3 5 1 7 2 9 8 4 4 4 9 9 9 9 9 9 8 6SORT (ARR); printarr (arr); // 0 1 2 3 4 5 6 7 8 9}}}요약
위의 내용은 Java 프로그래밍 구현 빠른 정렬 및 최적화 코드에 대한 자세한 설명입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!