快速排序, 堆排序,归并排序都是时间复杂度为O(N*logN)的几种常见排序方法,也是排序中复杂度较低的几种算法。
一、快速排序[不稳定]
1、原理:分治+递归
2、复杂度:O(nlgn) - O(nlgn) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]
3、栈空间O(lgn) - O(n)
4、原理:参看文章:快速排序原理
public static void Quicksort(int[] nums, int s, int e) {
// 递归的结束条件
if (null == nums || (e - s) < 1) {
return;
}
int pivo = nums[s];
int start = s;
int end = e;
// 注意下面的start < end的判断是不可缺少的
while (start < end) {
while (start < end && nums[end] >= pivo) {
end--;
}
if (start < end) {
nums[start] = nums[end];
start++;
}
while (start < end && nums[start] <= pivo) {
start++;
}
if (start < end) {
nums[end] = nums[start];
end--;
}
}
nums[start] = pivo;
// 递归
Quicksort(nums, s, start-1);
Quicksort(nums, start+1, e);
}
二、堆排序[不稳定]
1、堆一般指二叉堆。
2、复杂度:O(nlogn) - O(nlgn) - O(nlgn) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]
3、大顶堆实现从小到大的升序排列,小顶堆一般用于构造优先队列
4、原理:参看文章:堆排序原理
public static void Heapsort(int[] a) {
if (null == a || a.length < 2) {
return;
}
buildMinHeap(a);
// 堆排序
for (int i = a.length - 1; i >= 0; i--) {
int temp = a[0];
a[0] = a[i];
a[i] = temp;
adjustHeap(a, i, 0);
}
}
//创建堆
public static void buildMinHeap(int[] a) {
int mid = a.length/2;
for (int i = mid; i >= 0; i--) {
adjustHeap(a, a.length, i);
}
}
public static void adjustHeap(int[] a, int size, int parent) {
int left = parent * 2 + 1;
int right = parent * 2 + 2;
int min = parent;
if (left < size && a[min] > a[left]) {
min = left;
}
if (right < size && a[min] > a[right]) {
min = right;
}
if (parent != min) {
int tmp = a[parent];
a[parent] = a[min];
a[min] = tmp;
adjustHeap(a, size, min);
}
}
三、归并排序[稳定]
1、复杂度:O(nlogn) - O(nlgn) - O(nlgn) - O(n)[平均 - 最好 - 最坏 - 空间复杂度]
2、原理:参看文章:归并排序
public static void mergeSort(int[] a, int low, int high) {
int mid = (low + high)/2;
if (low < high) {
// 左边排序
mergeSort(a, low, mid);
// 右边排序
mergeSort(a, mid+1, high);
// 左右合并
merge(a, low, mid, high);
}
}
public static void merge(int[] a, int low, int mid, int high) {
int[] tmp = new int[high-low+1];
int index=0;
int i = low;
int j = mid +1;
while (i <= mid && j <= high) {
if (a[i] < a[j]) {
tmp[index++] = a[i++];
} else {
tmp[index++] = a[j++];
}
}
// 把左边剩余的数移入数组
while (i <= mid) {
tmp[index++] = a[i++];
}
// 把右边剩余的数移入数组
while(j <= high) {
tmp[index++] = a[j++];
}
for (int t = 0; t < tmp.length; t++) {
a[low+t] = tmp[t];
}
}