九大排序算法简单集合
本人刚学习完排序算法,看的是《数据结构与算法分析(Java描述版)(第四版)》,与C描述版还是有些不一样的地方,写下此博客与各位初学者分享,代码中已写好详细的注释,也分析了各种算法的适用场合,如有不懂可以留言。最后给出了Github上源代码获取网址,建议在IDE中边看边测试。第一次写,写得不好的地方请谅解。
- 插入排序
- 直接插入排序
- 希尔排序
- 选择排序
- 直接选择排序
- 堆排序
- 交换排序
- 冒泡排序
- 快速排序
- 归并排序
- 基数排序
- 外部排序
/*
* ┏┓ ┏┓+ +
* ┏━┛┻━━━━━━┛┻━┓ + +
* ┃ ┃ + + +
* ┃ ━ ┃ + + + +
* ┃ ████━████ ┃
* ┃ ┃ + +
* ┃ ┻ ┃
* ┃ ┃ +
* ┗━━┓ ┏━━┛
* ┃ ┃
* ┃ ┃ + + + +
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ + 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃ +
* ┃ ┗━━━━━━━┓ + +
* ┃ ┣━┓
* ┃ ┏━┛
* ┗━┓ ┓ ┏━━┳━┓ ┏━┛ + + + +
* ┃ ┫ ┫ ┃ ┫ ┫
* ┗━┻━┛ ┗━┻━┛+ + + +
*/
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
/**
* 多种排序算法集合
* 为什么快排在实际使用中通常优于堆排序?
* 局部性原理,越靠近的数据比较和交换用时越少,而且CPU的Cache中缓存了最近频繁读写的数据。
* 在堆排中,每一个操作都是不利于程序的局部性原理的,每次元素间的比较、数的调整等,
* 最大堆调整每次都从堆底拿元素换到堆顶然后又下滤下去,在堆底一般都比较小,很大可能再次下滤到底层,
* 这个过程做了很多无用功,需要不断地跨度大地读写数据。
* 反观快速排序和归并排序,利用分而治之的方法,元素间的比较都在某个段内,操作比较集中,局部性相当好。
*
* 快排<归并<堆排<希尔<<<插入<选择<冒泡
*
* @author Macer_YGG
* @version V1.1
* @date 2018/04/30 23:08
*/
public class SortDemo {
/**
* timer 计时用
*/
private static long timer;
/**
* Simple insertion sort 直接插入排序
* 每步将一个待排序的元素,按大小插入前面已经排序的序列中适当位置上,直到全部插入完为止
* 时间复杂度O(n^2),空间复杂度O(1),稳定
* 适用场合:数据量不大,对算法的稳定性有要求,且数据局部或者整体有序的情况,小规模如10个数平均时间最快,可以在快排中调用
*
* @param a an array of Comparable items.
* @param <T> 实现Comparable接口的类
*/
public static <T extends Comparable<? super T>> void insertionSort(T[] a) {
long start = System.currentTimeMillis();
int j;
T tmp;
// 从第二个元素开始,向前试探性插入
for (int i = 1; i < a.length; i++) {
if (a[i].compareTo(a[i - 1]) < 0) {
// 将当前元素暂存
tmp = a[i];
// 向前比较,若符合要求则将比较项往右移存
for (j = i; j > 0 && tmp.compareTo(a[j - 1]) < 0; j--) {
a[j] = a[j - 1];
}
// 插入
a[j] = tmp;
}
}
timer = System.currentTimeMillis() - start;
}
/**
* ShellSort 希尔排序
* 是插入排序的一种又称"缩小增量排序"(Diminishing Increment Sort)
* 使用简单的希尔增量序列,复杂的增量序列中Sedgewick 增量序列最坏时间复杂度达到O(n^1.3)
* 时间复杂度取决于增量序列,空间复杂度O(1),不稳定!!!
* 适用场合:数据量较大,不要求稳定性
*
* @param a an array of Comparable items.
* @param <T> 实现Comparable接口的类
*/
public static <T extends Comparable<? super T>> void shellSort(T[] a) {
long start = System.currentTimeMillis();
T tmp;
int j;
// 使用希尔增量序列
for (int gap = a.length / 2; gap > 0; gap /= 2) {
// 里层用的是直接插入排序算法
for (int i = gap; i < a.length; i++) {
if (a[i].compareTo(a[i - gap]) < 0) {
tmp = a[i];
for (j = i; j >= gap && tmp.compareTo(a[j - gap]) < 0; j -= gap) {
a[j] = a[j - gap];
}
a[j] = tmp;
}
}
}
timer = System.currentTimeMillis() - start;
}
/**
* SelectionSort 直接选择排序
* 每一次从待排序的数据元素中选出最小的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完
* 时间复杂度O(n^2),空间复杂度O(1),不稳定
* 适用场合:当数据量不大,且对稳定性没有要求的时候
*
* @param a an array of Comparable items.
* @param <T> 实现Comparable接口的类
*/
public static <T extends Comparable<? super T>> void selectionSort(T[] a) {
long start = System.currentTimeMillis();
// 第 i+1 个最小元素位置标记
int minIndex;
T tmp;