版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012292754/article/details/88431377
原地 | 稳定 | 最好 | 最坏 | 平均 | |
---|---|---|---|---|---|
归并 | ✘ | ✔ | O(N logN) | O(N logN) | O(N logN) |
快排 | ✔ | ✘ | O(N logN) | O(N^2) | O(N logN) |
1 归并排序(Merge sort)
package sort;
import java.util.Arrays;
public class MergeSort {
public static void mergeSort(int[] nums, int numsLength) {
mergeSortInternally(nums, 0, numsLength - 1);
}
private static void mergeSortInternally(int[] nums, int numsStart, int numsEnd) {
if (numsStart >= numsEnd) {
return;
}
int mid = numsStart + (numsEnd - numsStart) / 2;
mergeSortInternally(nums, numsStart, mid);
mergeSortInternally(nums, mid + 1, numsEnd);
merge(nums, numsStart, numsEnd, mid);
}
private static void merge(int[] nums, int numsStart, int numsEnd, int mid) {
int preIndex = numsStart;
int backIndex = mid + 1;
int tmpIndex = 0;
int[] tmp = new int[numsEnd - numsStart + 1];
while (preIndex <= mid && backIndex <= numsEnd) {
if (nums[preIndex] <= nums[backIndex]) {
tmp[tmpIndex++] = nums[preIndex++];
} else {
tmp[tmpIndex++] = nums[backIndex++];
}
}
int remainStart = preIndex;
int remianEnd = mid;
if (backIndex <= numsEnd) {
remainStart = backIndex;
remianEnd = numsEnd;
}
while (remainStart <= remianEnd) {
tmp[tmpIndex++] = nums[remainStart++];
}
// 将tmp 拷贝回 nums[numsStart,...,numsEnd]
for (int j = 0; j < tmpIndex; j++) {
nums[numsStart + j] = tmp[j];
}
}
public static void main(String[] args) {
int[] nums = {9, 8, 7, 6, 5, 4, 3, 2, 1};
mergeSort(nums, nums.length);
System.out.println(Arrays.toString(nums));
}
}
2 快排
package sort;
import java.util.Arrays;
public class QuickSort {
public static void quickSort(int[] nums, int numsLength) {
quickSortInternally(nums, 0, numsLength - 1);
}
private static void quickSortInternally(int[] nums, int numsStart, int numsEnd) {
if (numsStart >= numsEnd) {
return;
}
int segIndex = partition(nums, numsStart, numsEnd);
quickSortInternally(nums, numsStart, segIndex - 1);
quickSortInternally(nums, segIndex + 1, numsEnd);
}
/**
* i 把 nums[numsStart,...,numsEnd-1] 分成两部分;
* nums[numsStart,...,i-1] 元素小于 pivot, 称为已处理区间;
* nums[i,...,numsEnd-1] 是未处理区间;
* 每次从 nums[i,..,numsEnd-1] 取一个元素 nums[k] 与 pivot 对比
* 小于pivot,则将其加入已处理区间尾部,也就是 A[i] 的位置
* */
private static int partition(int[] nums, int numsStart, int numsEnd) {
int pivot = nums[numsEnd];
int i = numsStart;
for (int k = numsStart; k < numsEnd; ++k) {
if (nums[k] < pivot) {
if (i == k) {
++i;
}else{
int tmp = nums[i];
nums[i++] = nums[k];
nums[k] = tmp;
}
}
}
int tmp = nums[i];
nums[i] = nums[numsEnd];
nums[numsEnd] = tmp;
return i;
}
public static void main(String[] args) {
int[] nums = {3, 2, 1, 4, 9, 7, 6};
quickSort(nums, nums.length);
System.out.println(Arrays.toString(nums));
}
}
3 二分法 O(log N)
3.1 二分法注意
- 循环退出条件:
low <= high
- mid 的取值;
- low 和 high 的更新,
3.2 二分法的局限性
- 依赖顺序表结构,就是数组;
- 针对的是有序的数组
package sort;
public class Bsearch {
public static int bsearch(int[] nums, int len, int val) {
int low = 0;
int high = len - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (nums[mid] == val) {
return mid;
} else if (nums[mid] < val) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
// 递归实现
public static int bsearch_2(int[] nums, int len, int val) {
return bsearchInternally(nums, 0, len - 1, val);
}
private static int bsearchInternally(int[] nums, int low, int high, int val) {
if (low > high) {
return -1;
}
int mid = low + (high - low) / 2;
if (nums[mid] == val) {
return mid;
} else if (nums[mid] < val) {
return bsearchInternally(nums, mid + 1, high, val);
} else {
return bsearchInternally(nums, low, mid - 1, val);
}
}
public static void main(String[] args) {
int[] nums = {6, 5, 4, 3, 2};
int index = bsearch(nums, nums.length, 4);
System.out.println(index);
}
}