快速排序
经典快排中,每次选择区间的最后一个数进行partition过程,这个跟数据状态是有关系的,如果数据一开始是逆序的,那么复杂度会变为O(N^2)。改进后的快排中,每次随机选择一个数进行partition过程,复杂度的长期期望为O(N*log(N))。空间复杂度为O(log(N))。
public static void quickSort(int[] arr, int l, int r) {
if (l >= r) {
return ;
}
int p = arr[l + (int) (Math.random() * (r-l+1))];
int[] res = partision(arr, l, r, p);
quickSort(arr, l, res[0]-1);
quickSort(arr, res[1]+1, r);
}
public static int[] partision(int[] arr, int l, int r, int p) {
int less = l - 1;
int more = r + 1;
while (l < more) {
if (arr[l] < p) {
swap(arr, ++less, l++);
} else if (arr[l] > p) {
swap(arr, --more, l);
} else {
l++;
}
}
return new int[]{ less + 1, more - 1 };
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
堆排序
根据数组构建一个堆结构(heapInsert),然后每次将堆顶的数与堆中的最后一个数交换,将堆的大小减一,重新调整堆结构(heapify)。(每搞定一个数,代价为O(logN), 所以复杂度为O(N*logN))。空间复杂度为O(1)。
public static void heapSort(int[] arr) {
for (int i=0; i<arr.length; ++i) {
heapInsert(arr, i);
}
int heapSize = arr.length-1;
while (heapSize > 0) {
swap(arr,0,heapSize);
heapSize -= 1;
heapify(arr,0, heapSize);
}
}
public static void heapInsert(int[] arr, int i) {
while (arr[i] > arr[(i-1)/2]) {
swap(arr, i, (i-1)/2);
i = (i-1)/2;
}
}
public static void heapify(int[] arr, int i, int size) {
while(i < size) {
// 找出三个数中值最大且在堆中的那个
int largest = 0;
if (2*i+1 > size) {
// 无左子树
return ;
} else if (2*i+2 > size) {
// 无右子树
largest = arr[i] >= arr[2*i+1] ? i : (2*i+1);
} else {
// 左右子树都有
largest = arr[i] >= Math.max(arr[2*i+1], arr[2*i+2]) ? i : (arr[2*i+1] >= arr[2*i+2]) ? 2*i+1 : 2*i+2;
}
if (largest == i) {
return ;
} else {
swap(arr, i, largest);
i = largest;
}
}
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
桶排序
非基于比较的排序,时间复杂度O(N), 空间复杂度O(N)。虽然很快,但是实际应用中有它的局限性,重要性不如基于比较的排序。
public static void bucketSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
//求出这组数中的最大值
int max = Integer.MIN_VALUE;
for (int x: arr) {
max = x > max ? x : max;
}
int[] help = new int[max+1];
for ( int x: arr) {
help[x] += 1;
}
int i=0;
for (int j = 0; j < help.length; j++) {
while (help[j]-- > 0) {
arr[i++] = j;
}
}
}