部分素材来自网络,若不小心影响到您的利益,请联系博主删除。
- 学习视频:https://www.bilibili.com/video/BV1iJ411E7xW
- 课程配套资料:https://pan.baidu.com/s/1wxKSQw8exCdqFek-VDrSPg(提取码:jkg9)
- 写这篇博客旨在制作笔记,方便个人在线阅览,巩固知识。无他用。
- 博客的内容主要来自上述视频中的内容和其资料中提供的学习笔记。
首先创建一个工具类(封装后面这些常用的方法),之后再研究排序算法
public class Utils {
// 比较 v 元素是否大于 w 元素
// v 元素大于 w 元素,即返回 true。否则返回 false
static boolean greater(Comparable v, Comparable w) {
return v.compareTo(w) > 0;
}
// 判断 v 是否小于 w
static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
// 交换 a 数组中,索引 i 和索引 j 处的值
static void exchange(Comparable[] a, int i, int j) {
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
排序原理
public class BubbleSort {
// 对数组 a 中的元素进行排序(从小到大排序)
public static void sort(Comparable[] a) {
for (int i = a.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (greater(a[j], a[j + 1])) {
exchange(a, j, j + 1);
}
}
}
}
}
排序原理
public class SelectSort {
// 对数组 a 中的元素进行排序(从小到大排序)
public static void sort(Comparable[] a) {
for (int i = 0; i < a.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < a.length; j++) {
if (greater(a[minIndex], a[j])) {
minIndex = j; // 找到最小值的索引
}
}
exchange(a, minIndex, i);
}
}
}
排序原理
public class InsertSort {
// 对数组 a 中的元素进行排序(从小到大排序)
public static void sort(Comparable[] a) {
// 当前元素 a[i],依次和 i 前面的元素比较,找到一个小于等于 a[i] 的元素
for (int i = 1; i < a.length; i++) {
for (int j = i; j > 0; j--) {
if (greater(a[j - 1], a[j])) {
exchange(a, j - 1, j);
} else {
break;
}
}
}
}
}
排序原理
间隙值 gap 的确定:间隙值 gap 遵循着固定的规则
我们这里采用以下规则
int gap = 1;
// 这里的 a 是数组,若它的长度是 10 的话
while(gap < a.length / 2){
gap = 2 * gap + 1;// 3, 7
}
// 循环结束后我们就可以确定 gap 的最大值了
// gap 的减小规则如下
gap= gap / 2
public class ShellSort {
public static void sort(Comparable[] a) {
int gap = 1;
while (gap < a.length / 2) {
gap = gap * 2 + 1;
}
while (gap >= 1) {
for (int i = gap; i < a.length; i++) {
for (int j = i; j >= gap; j -= gap) {
if (greater(a[j - gap], a[j])) {
exchange(a, j - gap, j);
} else {
break;
}
}
}
gap = gap / 2;
}
}
}
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用 分治法 的一个非常典型的应用。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
若将两个有序表合并成一个有序表,称为二路归并。
排序原理
归并排序 API 设计
类名 | MergeSort |
---|---|
成员方法 | 1. public static void sort(Comparable[] a) :对数组内的元素进行排序2. private static void sort(Comparable[] a, int low, int high) :对数组 a 中从索引 low 到索引 high 之间的元素进行排序 3. private static void merge(Comparable[] a, int low, int midth, int high) :从索引 low 到索引 middle 为一个子组,从索引 middle + 1 到索引 high 为另一个子组, 把数组 a 中的这两个子组的数据合并成一个有序的大组(从索引 low 到索引 high) |
成员变量 | private static Comparable[] assist :完成归并操作需要的辅助数组 |
public class MergeSort {
private static Comparable[] assist;
public static void sort(Comparable[] a) {
assist = new Comparable[a.length];
int low = 0;
int high = a.length - 1;
sort(a, low, high);
}
private static void sort(Comparable[] a, int low, int high) {
if (high <= low) {
return;
}
int middle = (low + high) >>> 1;
sort(a, low, middle);
sort(a, middle + 1, high);
merge(a, low, middle, high);
}
private static void merge(Comparable[] a, int low, int middle, int high) {
int index = low, left = low, right = middle + 1;
while (left <= middle && right <= high) {
if (less(a[left], a[right])) {
assist[index++] = a[left++];
} else {
assist[index++] = a[right++];
}
}
// 下面两个循环只会执行一个循环
while (left <= middle) {
assist[index++] = a[left++];
}
while (right <= high) {
assist[index++] = a[right++];
}
for (int tmp = low; tmp <= high; tmp++) {
a[tmp] = assist[tmp];
}
}
}
快速排序是对冒泡排序的一种改进。
基本思想
排序原理
快速排序API设计
类名 | QuickSort |
---|---|
成员方法 | 1. public static void sort(Comparable[] a) :对数组内的元素进行排序2. private static void sort(Comparable[] a, int low, int high) :对数组 a 中从索引 low 到索引 high 之间的元素进行排序 3. public static int partition(Comparable[] a, int low, int high) :对数组 a 中,从索引 low 到索引 high 之间的元素进行分组,并返回分组界限对应的索引 |
切分原理 把一个数组切分成两个子数组的基本思想:
public class QuickSort {
public static void sort(Comparable[] a) {
int low = 0;
int high = a.length - 1;
sort(a, low, high);
}
private static void sort(Comparable[] a, int low, int high) {
if (high <= low) {
return;
}
int partition = partition(a, low, high);
sort(a, low, partition - 1);
sort(a, partition + 1, high);
}
public static int partition(Comparable[] a, int low, int high) {
int left = low;
int right = high + 1;
while (true) {
while (less(a[low], a[--right])) {
if (right == low) {
break;
}
}
while (less(a[low], a[++left])) {
if (left == high) {
break;
}
}
if (left >= right) {
break; // 扫描完毕,结束循环
} else {
exchange(a, left, right);
}
}
exchange(a, low, right);
return right;
}
}
快速排序 和 归并排序 的区别:
常见排序算法的稳定性: