算法系列(二)冒泡排序、选择排序、插入排序和希尔排序(Java实现)

xiaoxiao2021-02-28  64

前言:算法第四版2.1节 初级排序算法 学习总结,这里排序的结果都是从大到小。

冒泡排序:

1.从第一个元素开始,比较相邻元素大小,如果后面的元素比前面的元素小则互换位置,一轮结束后,最后一个元素是最大的

2.除去最后一个元素(已经有序了),进行1,倒数第二个位置是剩下的元素中最大的

3.以此类推

速度:正序时是最好情况O(n),逆序时是最坏情况O(n^2)

/** * 冒泡排序 * @author CANAAN * */ public class BubbleSort { public static void sort(Comparable[] a){ for (int i = 0; i < a.length - 1; i++){ for (int j = 0; j < a.length-1-i; j++){ if (less(a[j+1], a[j])){ exch(a,j,j+1); } } } } private static boolean less(Comparable v, Comparable w){ //比较v是否小于w return v.compareTo(w) < 0; } private static void exch(Comparable[] a, int i, int j) { //交换 Comparable t = a[i]; a[i] = a[j]; a[j] = t; } public static void show(Comparable[] a){ //单行打印数组 for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } System.out.println(); } public static boolean isSorted(Comparable[] a){ //判断是否有序 for (int i = 1; i < a.length; i++) { if(less(a[i], a[i-1])) return false; } return true; } /*public static void main(String[] args) { String[] a = StdIn.readAllStrings(); sort(a); show(a); }*/ }

选择排序:

1.找到数组中最小的元素与数组中第一个元素交换位置

2.在剩下的元素中找到最小的元素和数组中第二个元素交换位置

3.以此类推

速度:对于大小为N的数组,需要N^2/2次比较和N次交换。(数据移动是最少的)

/** * 选择排序 * @author Chuanjie * */ public class SelectionSort { public static void sort(Comparable[] a){ int N = a.length; for (int i = 0; i < N; i++) { int min = i; for (int j = i+1; j < N; j++) { if(less(a[j],a[min])) min = j; exch(a, i, min); } } } private static boolean less(Comparable v, Comparable w){ //比较v是否小于w return v.compareTo(w) < 0; } private static void exch(Comparable[] a, int i, int j) { //交换 Comparable t = a[i]; a[i] = a[j]; a[j] = t; } public static void show(Comparable[] a){ //单行打印数组 for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } System.out.println(); } public static boolean isSorted(Comparable[] a){ //判断是否有序 for (int i = 1; i < a.length; i++) { if(less(a[i], a[i-1])) return false; } return true; } }

插入排序:

1.从第二个元素开始,与左边的元素倒序逐个比较,比它大就交换位置,直到位于合适位置使左边序列有序

速度:平均需要~N^2/4次比较和~N^2/4次交换;最坏情况需要~N^2/2次比较和~N^2/2次交换;最好情况需要N-1次比较和0次交换。

通常,插入排序要比冒泡和选择快。

使用场景:对接近有序或部分有序的序列排序

/** * 插入排序 * @author Chuanjie * */ public class InsertionSort { public static void sort(Comparable[] a){ int N = a.length; for (int i = 1; i < N; i++) { for (int j = i; j > 0 && less(a[j],a[j-1]); j--) { exch(a,j,j-1); } } } private static boolean less(Comparable v, Comparable w){ //比较v是否小于w return v.compareTo(w) < 0; } private static void exch(Comparable[] a, int i, int j) { //交换 Comparable t = a[i]; a[i] = a[j]; a[j] = t; } public static void show(Comparable[] a){ //单行打印数组 for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } System.out.println(); } public static boolean isSorted(Comparable[] a){ //判断是否有序 for (int i = 1; i < a.length; i++) { if(less(a[i], a[i-1])) return false; } return true; } }

希尔排序:

思路:使间隔h的元素组成的数组有序,发挥插入排序的优势(h=1时就是插入排序)

1.选择一个增量序列,一般有3*h+1、2^n-1

2.从最大的h开始往下,对h个子序列进行插入排序,直到h=1

速度:性能与选取的h序列有关,最坏时与N^(3/2)成正比(突破了平方级);使用3*h+1序列的希尔排序所需的比较次数不会超出N的若干倍乘以递增序列的长度

使用场景:无更高效的排序算法时(明显提升了插入排序的性能);嵌入式系统里(代码量小,不需要额外的内存空间)

/** * 希尔排序:h-sort * 以h为步长划分为若干子数组进行插入排序 * 这里选择的递增序列是 3*h+1 * @author Chuanjie * */ public class ShellSort { public static void sort(Comparable[] a){ int N = a.length; int h = 1; while(h < N/3) h = 3*h +1; while(h>=1){ for (int i = h; i < N; i++) { for (int j = i; j >= h && less(a[j],a[j-h]) ; j-=h) { exch(a,j,j-h); } } h = h/3; } } private static boolean less(Comparable v, Comparable w){ //比较v是否小于w return v.compareTo(w) < 0; } private static void exch(Comparable[] a, int i, int j) { //交换 Comparable t = a[i]; a[i] = a[j]; a[j] = t; } public static void show(Comparable[] a){ //单行打印数组 for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } System.out.println(); } public static boolean isSorted(Comparable[] a){ //判断是否有序 for (int i = 1; i < a.length; i++) { if(less(a[i], a[i-1])) return false; } return true; } }

总结:

1.排序算法的使用场景很多,结合实例学习便于理解,比如写一个扑克游戏,随机发牌的实现就是逆着使用排序算法(生成随机数);在寻找凸包(convex hull)时使用的Graham scan核心也是排序算法(排列极角)

2. 算法效率的数学模型是一个复杂的问题,通过实例去分析,不要纠结精确的性能分析。

转载请注明原文地址: https://www.6miu.com/read-58250.html

最新回复(0)