动画详解十大经典排序算法Java版实现(上)
Posted 盛夏温暖流年
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动画详解十大经典排序算法Java版实现(上)相关的知识,希望对你有一定的参考价值。
经典排序算法可以说是面试必考题,然而大学毕业之后基本都忘光了,正好趁这个机会拿出来好好总结复习下,也算不辜负当年老师的一片苦心了。
十大经典排序算法包括:冒泡排序,选择排序,插入排序,希尔排序,归并排序,快速排序,堆排序,计数排序,桶排序,基数排序。
本来准备一口气把十种都介绍一遍,然而整理完前五种后大脑就宕机了(亲测熬夜会使人变傻······),那干脆就分为上下两部分好了,正好也方便记忆。
接下来我们用动画的方式,先来分析前五种算法:冒泡排序,选择排序,插入排序,希尔排序,归并排序。
1. 冒泡排序
算法介绍
冒泡排序是一种简单的排序算法,它会重复遍历要排序的数列,一次比较两个元素,如果两个元素的顺序错误,就交换过来。
遍历数列需要重复进行,直到没有再需要交换的元素,才代表数列已经排序完成。
因为小的元素会经由交换慢慢“浮”到数列的顶端,就像水泡冒出来一样,所以才称之为“冒泡排序”。
动画演示
步骤描述
- 比较相邻的元素:如果第一个元素比第二个大,就交换它们;
- 比较每一对相邻元素并交换,从开始第一对到最后一对,这样最后的元素就是最大的数;
- 针对所有的元素重复以上步骤,除了最后一个;
- 重复前三个步骤,直到排序完成;
代码实现
public static void main(String[] args) {
int arr[] = {8, 5, 3, 2, 4};
//冒泡
for (int i = 0; i < arr.length; i++) {
//外层循环,遍历次数
for (int j = 0; j < arr.length - i - 1; j++) {
//内层循环,升序(如果后一个值比前一个值小,则交换)
//内层循环一次,获取一个最大值
if (arr[j + 1] < arr[j]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
2. 选择排序
算法介绍
选择排序是一种简单直观的排序算法。
它首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素放到已排序序列的末尾。
以此类推,直到所有元素全部排序完毕。
动画演示
步骤描述
- 将第一个值看成最小值;
- 和后续的值进行比较,找出最小值和下标;
- 交换本次遍历的起始值和最小值;
- 重复以上步骤直到列表排序结束;
代码实现
public static void main(String[] args) {
int arr[] = {6, 5, 3, 2, 4};
// 选择
for (int i = 0; i < arr.length; i++) {
// 默认第一个是最小的
int min = arr[i];
// 记录最小的下标
int index = i;
// 通过与后面的数据进行比较得出,最小值和下标
for (int j = i + 1; j < arr.length; j++) {
if (min > arr[j]) {
min = arr[j];
index = j;
}
}
//然后将最小值与本次循环的a[i]值进行交换
arr[index] = arr[i];
arr[i] = min;
}
}
3. 插入排序
算法介绍
对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
插入排序在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
动画演示
步骤描述
- 第一个元素默认已经被排序;
- 取出下一个元素,在已经排序的元素序列中从后向前扫描;
- 如果该元素大于新元素,将该元素移到下一位置;
- 重复上一步骤,直到找到已排序的元素<=新元素的位置;
- 将新元素插入到该位置;
- 重复步骤 2 ~ 5;
代码实现
public static void main(String[] args) {
int arr[] = {7, 5, 3, 2, 4};
//插入排序
for (int i = 1; i < arr.length; i++) {
//外层循环,从第二个开始比较
for (int j = i; j > 0; j--) {
//内层循环,与前面排好序的数据比较,如果后面的数据小于前面的则交换
if (arr[j] < arr[j - 1]) {
int temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
} else {
//如果不小于,说明插入完毕,退出内层循环
break;
}
}
}
}
4. 希尔排序
算法介绍
希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。它与插入排序的不同之处在于,它会优先比较距离较远的元素。
希尔排序会把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
动画演示
动画演示效果看起来不太好理解,我们可以通过以下图片进一步加深理解:
步骤描述
-
选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
-
按增量序列个数 k,对序列进行 k 趟排序;
-
每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序;
-
仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度;
代码实现
public static void main(String[] args) {
int arr[] = {7, 5, 3, 2, 4};
//希尔排序(插入排序变种版)
for (int i = arr.length / 2; i > 0; i /= 2) {
//i层循环控制步长
for (int j = i; j < arr.length; j++) {
//j控制无序端的起始位置
for (int k = j; k > 0 && k - i >= 0; k -= i) {
if (arr[k] < arr[k - i]) {
int temp = arr[k - i];
arr[k - i] = arr[k];
arr[k] = temp;
} else {
break;
}
}
}
//j,k为插入排序,不过步长为i
}
}
5. 归并排序
算法介绍
归并排序是建立在归并操作上的一种有效的排序算法。
该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,是一种稳定的排序方法。
排序规则是将已经有序的子序列进行合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
动画演示
步骤描述
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列;
代码实现
public static void main(String[] args) {
int arr[] = {7, 5, 3, 2, 4, 1,6};
//归并排序
int start = 0;
int end = arr.length - 1;
mergeSort(arr, start, end);
}
public static void mergeSort(int[] arr, int start, int end) {
//判断拆分的不为最小单位
if (end - start > 0) {
//再一次拆分,直到拆成单个数据
mergeSort(arr, start, (start + end) / 2);
mergeSort(arr, (start + end) / 2 + 1, end);
//记录开始/结束位置
int left = start;
int right = (start + end) / 2 + 1;
//记录每个小单位的排序结果
int index = 0;
int[] result = new int[end - start + 1];
//如果拆分后的两块数据都还存在
while (left <= (start + end) / 2 && right <= end) {
//比较两块数据的大小,然后赋值,并且移动下标
if (arr[left] <= arr[right]) {
result[index] = arr[left];
left++;
} else {
result[index] = arr[right];
right++;
}
//移动单位记录的下标
index++;
}
//当某一块数据不存在
while (left <= (start + end) / 2 || right <= end) {
//直接赋值到记录下标
if (left <= (start + end) / 2) {
result[index] = arr[left];
left++;
} else {
result[index] = arr[right];
right++;
}
index++;
}
//最后将新的数据赋值给原来的列表,并且是对应分块后的下标
for (int i = start; i <= end; i++) {
arr[i] = result[i - start];
}
}
}
看到归并排序脑子就不行了,本篇博客就到这里,我们下期再见。
参考了博客如下,在这里表示特别感谢:
以上是关于动画详解十大经典排序算法Java版实现(上)的主要内容,如果未能解决你的问题,请参考以下文章