归并排序
归并排序 Merge Sorted Array 左边排序,右边排序,左右两边合并 === 归并排序需要额外的空间用于合并(要倒腾出来,再倒腾回去)。
归并排序其本质是二叉树的后序遍历!即分治。
// 思想:左边排序、右边排序,然后再合并
public class 归并排序
{
public static void mergeSort(int[] nums) {
if (nums == null) {
throw new RuntimeException("array is null");
}
mergeSortHelper(nums, 0, nums.length - 1);
}
// 思想:左边排序、右边排序,然后再合并
static void mergeSortHelper(int[] nums, int start, int end) {
if (start == end) {
return;
}
// Divide
int mid = start + (end - start) / 2;
mergeSortHelper(nums, start, mid);
mergeSortHelper(nums, mid + 1, end);
// Conquer
merge(nums, start, end, mid);
}
private static void merge(int[] nums, int start, int end, int mid)
{
int[] helper = new int[end - start + 1];
int p1 = start, p2 = mid + 1;
int index = 0;
while (p1 <= mid && p2 <= end) {
if (nums[p1] < nums[p2]) {
helper[index++] = nums[p1++];
} else {
helper[index++] = nums[p2++];
}
}
if (p1 <= mid) {
while (p1 <= mid) {
helper[index++] = nums[p1++];
}
}
if (p2 <= end) {
while (p2 <= end) {
helper[index++] = nums[p2++];
}
}
for (int i = end; i >= start; i--) {
nums[i] = helper[--index];
}
}
public static void main(String[] args)
{
int[] array = {1,5,7,2};
mergeSort(array);
for (int i : array)
{
System.out.println(i);
}
}
}
快速排序
快速排序 ==任取一个数target,将数组分成两部分,左边的<= target, 右边的 > target。然后左右两边再quick sort.复杂的在最坏的情况下是o(n2) 平均复杂度O(nlgn).
快速排序的本质是前序遍历。
// 思想:一个数组,随机找一个数字target,并将其放到正确的位置上(左边的数<=target,右边的数>target);然后左右两侧亦如此
public class 快速排序
{
public static void quickSort(int[] nums) {
if (nums == null) {
throw new RuntimeException("array is null");
}
quickSortHelper(nums, 0, nums.length - 1);
}
// position是寻找到的随机数字
static void quickSortHelper(int[] nums, int start, int end) {
// 第一步:将index = position的值归还到正确位置
Random random = new Random(end - start);
int position = random.nextInt() + start;
int target = nums[position];
int p1 = start, p2 = end;
while (p1 < p2) {
while (nums[p1] <= target && p1 < p2) {
p1++;
}
while (nums[p2] > target && p1 < p2) {
p2--;
}
if (p1 < p2) {
swap(nums, p1, p2);
}
}
quickSortHelper(nums, start, p1 - 1);
quickSortHelper(nums, p1 - 1, end);
}
private static void swap(int[] nums, int p1, int p2)
{
int temp = nums[p1];
nums[p1] = nums[p2];
nums[p2] = temp;
}
}
整体来说快拍优于归并排序,因为归并排序,需要额外的空间,然后将两个排序数组倒腾进去,然后再倒腾回去。。工程上常用快排
但是归并排序有个很好的地方,就是,其是稳定排序,而快拍不稳定。