Java资深小白,不足之处,或者有任何错误欢迎指出。 --蓝紫
冒泡排序(Bubble Sort)
算法描述:
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
- 对每一个相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
- 针对所有的元素重复以上的步骤,除了最后一个;
- 重复步骤1~3,直到排序完成。
排序方法 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n²) | O(n²) | O(n) | O(1) | 稳定 |
- 如果两个元素相等,不会再交换位置,所以冒泡排序是一种稳定的排序算法。
代码实现:
public static void bubbleSort(int[] data) {
int arrayLength = data.length;
// 第 i 次排序
for (int i = 1; i < arrayLength; i++) {
// 从索引为 j 的数开始
for (int j = 0; j < arrayLength - i; j++) {
// 相邻元素两两对比
if (data[j] > data[j + 1]) {
// 元素交换
int temp = data[j + 1];
data[j + 1] = data[j];
data[j] = temp;
}
}
System.out.println("第" + i + "次排序:\n" + java.util.Arrays.toString(data));
}
}
public static void main(String[] args) {
int[] data = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
bubbleSort(data);
System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
}
选择排序(Select Sort)
算法描述:
- 对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换;
- 对不包括第一个记录以外的其他记录进行第二轮比较,得到最小的记录与第二个记录进行位置交换;
- 重复该过程,直到进行比较的记录只有一个时为止。
排序方法 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
选择排序 | O(n²) | O(n²) | O(n²) | O(1) | 不稳定 |
代码实现:
/**
* 选择排序方式一
*
* @param a
*/
public static void selectSort(int[] a) {
int length = a.length;
// 最后一个元素无需和自己比较
for (int i = 0; i < length - 1; i++) {
for (int j = i + 1; j < length; j++) {
if (a[i] > a[j]) {
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
}
}
/**
* 方式二:先找出最小的元素下标
*
* @param a
*/
public static void selectSort2(int[] a) {
int length = a.length;
for (int i = 0; i < length - 1; i++) {
// 最小元素下标
int min = i;
// 找出最小值的下标
for (int j = i + 1; j < length; j++) {
if (a[j] < a[min]) {
min = j;
}
}
// 将最小值放到未排序记录的第一个位置
if (min > i) {
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
}
public static void main(String[] args) {
int[] data = { 3, 44, 38, 5, 43, 15, 34, 26, 27, 2, 46, 4, 19, 50, 48 };
System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
selectSort(data);
System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
}
快速排序(Quick Sort)
算法描述:
- 使用分治法来把一个串(list)分为两个子串(sub-lists)。具体描述如下:
- 从数列中跳出一个元素,称为“基准”(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准元素的子数列和大于基准值元素的子数列排序。
排序方法 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
快速排序 | O(n l o g 2 n log_2n log2n) | O(n²) | O(n l o g 2 n log_2n log2n) | O(n l o g 2 n log_2n log2n) | 不稳定 |
- key值的选取可以有多种形式,例如中间数或者随机数,分别会对算法的复杂度产生不同的影响。
代码实现:
public static void quickSort(int[] data, int low, int high) {
int i, j, temp, t;
if (low > high) {
return;
}
i = low;
j = high;
// temp 就是基准位
temp = data[low];
System.out.println("基准位:" + temp);
while (i < j) {
// 先看右边,依次往左递减
while (temp <= data[j] && i < j) {
j--;
}
// 再看左边,依次往右递增
while (temp >= data[i] && i < j) {
i++;
}
// 如果满足条件则交换
if (i < j) {
System.out.println("交换:" + data[i] + "和" + data[j]);
t = data[j];
data[j] = data[i];
data[i] = t;
System.out.println(Arrays.toString(data));
}
}
// 最后将基准位与 i 和 j 相等位置的数字交换
System.out.println("基准位" + temp + "和 i、j 相遇的位置" + data[i] + "交换");
data[low] = data[i];
data[i] = temp;
System.out.println(Arrays.toString(data));
// 递归调用左半数组
quickSort(data, low, j - 1);
// 递归调用右半数组
quickSort(data, j + 1, high);
}
public static void main(String[] args) {
int[] data = { 3, 36, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
System.out.println("排序之前:\n" + Arrays.toString(data));
quickSort(data, 0, data.length - 1);
System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
}
归并排序(Merge Sort)
算法描述:
- 把长度为n的输入列序分为两个长度为n/2的子序列;
- 对这两个子序列采用归并排序;
- 将两个排序好的子序列合并成为一个最终的排序序列。
排序方法 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
归并排序 | O(n l o g 2 n log_2n log2n) | O(n l o g 2 n log_2n log2n) | O(n l o g 2 n log_2n log2n) | O(n) | 稳定 |
代码实现:
public static void mergeSort(int[] arr) {
sort(arr, 0, arr.length - 1);
}
public static void sort(int[] arr, int L, int R) {
if (L == R) {
return;
}
int mid = L + ((R - L) >> 1);
sort(arr, L, mid);
sort(arr, mid + 1, R);
merge(arr, L, mid, R);
}
public static void merge(int[] arr, int L, int mid, int R) {
int[] temp = new int[R - L + 1];
int i = 0;
int p1 = L;
int p2 = mid + 1;
// 比较左右两部分的元素,哪个小,把那个元素填入temp中
while (p1 <= mid && p2 <= R) {
temp[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
// 上面的循环退出后,把剩余的元素依次填入到temp中
// 以下两个while只有一个会执行
while (p1 <= mid) {
temp[i++] = arr[p1++];
}
while (p2 <= R) {
temp[i++] = arr[p2++];
}
// 把最终的排序的结果复制给原数组
for (i = 0; i < temp.length; i++) {
arr[L + i] = temp[i];
}
}
public static void main(String[] args) {
int[] data = { 3, 44, 38, 5, 43, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
mergeSort(data);
System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
}