参考资料
快速排序
快速排序是不稳定的
切分算法的要点:
- 随机选择一个基准元素,为什么要随机,因为如果数组是有序或者逆序的情况下,会变得非常慢,等同于每次切分只返回第一个元素或者最后一个元素的坐标,这样二分算法就失去了意义了。
import java.util.Random;
class Solution {
private static final Random RANDOM = new Random();
public int[] sortArray(int[] nums) {
quickSort(nums,0,nums.length-1);
return nums;
}
public void quickSort(int[] nums,int start,int end){
if(start >= end){
return;
}
int k = partition(nums,start,end);
quickSort(nums,start,k-1);
quickSort(nums,k+1,end);
}
public int partition(int[] nums,int start,int end){
int randomIndex = RANDOM.nextInt(end - start + 1) + start;
swap(nums, start, randomIndex);
int priot = nums[start];
int index = start;// 循环不变量,保证区间[start,index-1]<priot,[index+1,end]>=priot是成立的
for(int i= start+1;i<=end;i++){
if(nums[i]<priot){
index++;
swap(nums,i,index);
}
}
swap(nums,start,index);
return index;
}
public void swap(int[] nums,int i, int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
插入排序
插入排序是稳定的。
- 总体思想:
- 将一个新的元素插入到一个有序数组中
- 在插入的过程中,需要移动比新的数大的数,所以用一个临时变量将新的数存储起来,后面的数覆盖掉前面的数
- 最后在挪出来的新位置放入新的数
- 插入排序的优势是:
内循环是可以提前终止的,如果顺序相对有序,或者是小数组,小数组直接的差距不是特别大,可以使用插入排序
public int[] sort(int[] nums) {
for (int i = 0; i < nums.length - 1; i++) {
int j = i + 1; // [0..i]是有序的,[0..j-1] <= tmp
int tmp = nums[j];
while (j > 0 && nums[j - 1] > tmp) {
nums[j] = nums[j - 1];
j--;
}
nums[j]=tmp;
}
return nums;
}
归并排序
归并排序是稳定的
public class MergeSort {
public void mergeSort(int[] nums) {
if (nums.length == 0) {
return;
}
int start = 0;
int end = nums.length - 1;
sort(start, end, nums);
}
private void sort(int start, int end, int[] nums) {
if (start >= end) {
return;
}
int middle = start + (end - start) / 2;
sort(start, middle, nums);
sort(middle + 1, end, nums);
merge(start, middle, middle + 1, end, nums);
}
private void merge(int left, int leftEnd, int right, int rightEnd, int[] nums) {
int k = 0;
int[] a = new int[rightEnd - left + 1];
int i = left;
int j = right;
while (i <= leftEnd || j <= rightEnd) {
if (i <= leftEnd && j <= rightEnd) {
if (nums[i] <= nums[j]) {
a[k++] = nums[i++];
} else {
a[k++] = nums[j++];
}
} else if (i <= leftEnd) {
a[k++] = nums[i++];
} else if (j <= rightEnd) {
a[k++] = nums[j++];
}
}
for (int l = left; l <= rightEnd; l++) {
nums[l] = a[l - left];
}
}
}