/*
* Copyright 2013 Websquared, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fastcatsearch.ir;
import java.util.Random;
import junit.framework.TestCase;
public class SortTest extends TestCase {
public void testInsertionSort() {
final int NUM = 10000000;
Random r = new Random();
int[] in = new int[NUM];
int[] in2 = new int[NUM];
for (int i = 0; i < NUM; i++) {
in[i] = r.nextInt(NUM);
// in[i] = i;
in2[i] = in[i];
}
System.out.println("Start!");
long st = System.currentTimeMillis();
// insertionSort(in,1,in.length-1);
// System.out.println("insertionSort = "+(System.currentTimeMillis() - st));
st = System.currentTimeMillis();
quickSort(in, 0, in.length - 1);
System.out.println("quickSort = " + (System.currentTimeMillis() - st));
st = System.currentTimeMillis();
quickSortIterative(in2, 0, in2.length - 1);
System.out.println("quickSortIterative = " + (System.currentTimeMillis() - st));
int prev = -1;
for (int i = 0; i < NUM; i++) {
// System.out.println(in2[i]);
if (in2[i] < prev) {
System.out.println("ERROR!!");
break;
}
prev = in2[i];
}
System.out.println("Done!");
}
void insertionSort(int[] list, int first, int last) {
int i, j, c;
for (i = first; i <= last; i++) {
j = list[i];
c = i;
while ((list[c - 1] > j) && (c > first)) {
list[c] = list[c - 1];
c--;
}
list[c] = j;
}
}
void quickSort(int[] numbers, int left, int right) {
int pivot, l_hold, r_hold;
l_hold = left;
r_hold = right;
pivot = numbers[left]; // 0번째 원소를 피봇으로 선택
while (left < right) {
// 값이 선택한 피봇과 같거나 크다면, 이동할 필요가 없다
while ((numbers[right] >= pivot) && (left < right))
right--;
// 그렇지 않고 값이 피봇보다 작다면,
// 피봇의 위치에 현재 값을 넣는다.
if (left != right) {
numbers[left] = numbers[right];
}
// 왼쪽부터 현재 위치까지 값을 읽어들이면서
// 피봇보다 큰은값이 있다면, 값을 이동한다.
while ((numbers[left] <= pivot) && (left < right))
left++;
if (left != right) {
numbers[right] = numbers[left];
right--;
}
}
// 모든 스캔이 끝났다면, 피봇값을 현재 위치에 입력한다.
// 이제 피봇을 기준으로 왼쪽에는 피봇보다 크거나 같은 값만 남았다.
numbers[left] = pivot;
pivot = left;
left = l_hold;
right = r_hold;
// 재귀호출을 수행한다.
if (left < pivot)
quickSort(numbers, left, pivot - 1);
if (right > pivot)
quickSort(numbers, pivot + 1, right);
}
private void quickSortIterative(int[] ids, int first, int last) {
if(last <= 0)
return;
int stackMaxSize = (int) ((Math.log(last) + 3) * 2);
int[][] stack = new int[stackMaxSize][2];
int pivotId = 0, sp = 0;
int left = 0, right = 0;
while(true){
while(first < last){
left = first;
right = last;
int pivot = (left + right)/2;
//move pivot to left most.
int tmp = ids[left];
ids[left] = ids[pivot];
ids[pivot] = tmp;
pivotId = ids[left];
while (left < right) {
while ((ids[right] - pivotId) >= 0 && (left < right))
right --;
if (left != right){
ids[left] = ids[right];
left++;
}
while ((ids[left] - pivotId) <= 0 && (left < right))
left ++;
if (left != right) {
ids[right] = ids[left];
right --;
}
}
ids[left] = pivotId;
if(left - first < last - left){
if (left + 1 < last) {
sp++;
stack[sp][0] = left + 1;
stack[sp][1] = last;
}
last = left - 1;
}else{
if (first < left - 1) {
sp++;
stack[sp][0] = first;
stack[sp][1] = left -1;
}
first = left + 1;
}
}
if (sp == 0) {
return;
}else {
first = stack[sp][0];
last = stack[sp][1];
sp--;
}
}
}
}