public static int partition(Integer[] arr, int left, int right) {
int i, j, x;
i = left - 1; // -1
j = left; // 0
x = arr[right]; // pivot
while (j <= right - 1) { // pivot - 1까지 순회
if (arr[j] <= x) { // pivot보다 작은 값이면
++i; // i 증가 시키고 스왑
swap(arr, i, j);
}
j++; // j 증가
}
swap(arr, i + 1, right); // pivot보다 작은 값만 앞에 남았으니 스왑
return i + 1; // 새 pivot 결정
}
public static int partition(Integer[] arr, int left, int right) {
int i = left;
int j = right;
while (i < j) {
while (arr[left] > arr[i]) { // pivot 비교
i++;
}
while (arr[left] <= arr[j] && i < j) { // pivot 비교, 인덱스 조건
j--;
}
if (i < j) {
swap(arr, i, j);
}
}
swap(arr, left, j);
return j;
}
public void quickSort(Node left, Node right) {
// 재귀 탈출 조건
if (right != null && left != right && left != right.next) {
Node temp = partition(left, right);
quickSort(left, temp.prev);
quickSort(temp.next, right);
}
}
Node partition(Node left, Node right) {
int pivot = right.data; // 우측 끝을 피벗으로 설정
Node i = left.prev; // 리스트의 시작 설정 배열로 치면 left - 1
// 배열에서 for(int j = left; j <= right - 1; j++) 과 같음
// 첫 리스트부터 끝 리스트까지 순회
for (Node j = left; j != right; j = j.next) {
if (j.data <= pivot) {
// 피벗이 작으면 i++과 같음
i = (i == null) ? left : i.next;
// 아니라면 swap
swap(i, j);
}
}
// 탈출 시 여전히 조건을 만족 한다면
i = (i == null) ? left : i.next;
swap(i, right);
return i;
}
핵심은 어떻게 가장 중간값에 가까운 pivot을 찾을 것인가?
public static void quickSort(Integer[] arr, int left, int right) {
int mid = (left + right) / 2;
int pivot, i, j;
threeSort(arr, left, right, mid);
if (right - left + 1 > 3) {
pivot = arr[mid];
swap(arr, mid, right - 1);
i = left;
j = right - 1;
//System.out.println("pivot = " + pivot);
while (true) {
while (arr[++i] < pivot);
while (arr[--j] > pivot);
if (i >= j) {
break;
}
swap(arr, i, j);
}
swap(arr, i, right - 1);
//System.out.println("arr = " + Arrays.deepToString(arr) + ", left = " + left + ", right = " + right);
quickSort(arr, left, i - 1);
quickSort(arr, i + 1, right);
}
}
public static void threeSort(Integer[] arr, int left, int right, int mid) {
if (arr[left] >= arr[mid]) swap(arr, left, mid);
if (arr[left] >= arr[right]) swap(arr, left, right);
if (arr[mid] >= arr[right]) swap(arr, mid, right);
}
public static int partition(Integer[] arr, int left, int right) {
Random r = new Random();
int pivot = r.nextInt(right - left) + left;
System.out.println("pivot = " + pivot);
int i = left;
int j = right;
swap(arr, left, pivot);
System.out.println("arr = " + Arrays.deepToString(arr) + ", left = " + left + ", right = " + right);
while (i < j) {
while (arr[left] > arr[i]) { // pivot >= data
i++;
}
while (arr[left] <= arr[j] && i < j) { // pivot <= data, outOfIndex
j--;
}
if (i < j) { // swap
swap(arr, i, j);
}
}
swap(arr, left, j); // pivot swap
System.out.println("arr = " + Arrays.deepToString(arr) + ", left = " + left + ", right = " + right);
return j;
}
시간 복잡도가 이라는 말은
실제 동작 시간은 라는 의미이다.
상대적으로 무시할 수 있는 부분인 부분을 제하면 에는 앞에 라는 상수가 곱해져 있어 이 값에 따라 실제 동작 시간에 큰 차이가 생긴다.
이 라는 값에 큰 영향을 끼치는 요소로 '알고리즘이 참조 지역성(Locality of reference) 원리를 얼마나 잘 만족하는가'가 있다.
(Naver D2 Tim sort 발췌)
어려운면서도 어렵던 정렬이였다.
영문 위키
퀵소트 vs 힙소트
합병,힙 vs 퀵소트
바킹독
프린스턴
퀵소트 정리
퀵소트 파헤치기
퀵소트 문제점
Doubly Linked list