写在前面的话:

一枚自学Java和算法的工科妹子。

  • 算法学习书目:算法(第四版) Robert Sedgewick
  • 算法视频教程:Coursera  Algorithms Part1&2

本文是根据《算法(第四版)》的个人总结,如有错误,请批评指正。

一、排序算法介绍

1.排序算法的目的:将所有元素的主键(如学生类,主键可以是姓名、学号、年龄等)按照某种方式排列(通常按照大小或字母排序)。

2.排序算法类模板:sort()排序方法;less()元素比较;exch()元素交换位置;show()打印字符数组内容;isSorted()判断元素是否有序。

 1 public class Example {
 2
 3     private Example () { }
 4
 5     public static void sort(Comparable[] a) {
 6       // 选择排序、插入排序、希尔排序、归并排序、快速排序,实现Comparable接口
 7     }
 8     public static void sort(Object[] a, Comparator comparator) {
 9       //  数据类型中定义内部类实现Comparator
10     }
11
12     // 判断元素大小
13     private static boolean less(Comparable v, Comparable w) {
14         return v.compareTo(w) < 0;
15     }
16     private static boolean less(Comparator comparator, Object v, Object w) {
17         return comparator.compare(v, w) < 0;
18     }
19
20     // 交换元素位置
21     private static void exch(Object[] a, int i, int j) {
22         Object swap = a[i];
23         a[i] = a[j];
24         a[j] = swap;
25     }
26
27     // 判断元素是否已排序
28     private static boolean isSorted(Comparable[] a, int lo, int hi) {
29         for (int i = lo + 1; i <= hi; i++)
30             if (less(a[i], a[i-1])) return false;
31         return true;
32     }
33
34     private static boolean isSorted(Object[] a, Comparator comparator, int lo, int hi) {
35         for (int i = lo + 1; i <= hi; i++)
36             if (less(comparator, a[i], a[i-1])) return false;
37         return true;
38     }
39
40     // 打印字符数组内容
41     private static void show(Comparable[] a) {
42         for (int i = 0; i < a.length; i++) {
43             StdOut.println(a[i]);
44         }
45     }
46 }

3.排序算法需要注意的问题

  • 验证:在测试代码中添加一条语句 assert isSorted(a) 来确认排序后数组元素都是有序的。
  • 运行时间:在研究排序算法时,我们需要计算比较和交换的数量。对于不交换元素的算法,我们会计算访问数组的次数。
  • 额外的内存使用:(1)原地排序算法:除了函数调用所需的栈和固定数目的实例变量之外无需额外内存;(2)其他排序算法:需要额外内存空间来存储另一份数组副本。
  • 数据类型:上述排序算法模板使用与实现了Comparable接口或者在类中定义了内部类实现Comparator接口的数据类型。Java中Integer、Double、String、File、URL等数据类型都实现了Comparable接口。当然也可以自己设计数据类型实现Comparable接口,实现compareTo()方法来自定义目标类型对象的自然次序。可参考Comparable和Comparator区别(实现和使用)。

二、初级排序算法

1. 选择排序介绍

1.1 选择排序算法流程

Step1:从待排序序列中,找到关键字最小的元素;

Step2:如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;

Step3:从余下的 N - 1 个元素中,找出关键字最小的元素,重复Step1和Step2,直到排序结束。

图1 选择排序的轨迹

1.2 选择排序算法代码实现

 1 import java.util.Comparator;
 2
 3 public class Selection {
 4
 5     private Selection() { }
 6
 7     public static void sort(Comparable[] a) {
 8         int n = a.length;
 9         for (int i = 0; i < n; i++) {
10             int min = i;
11             for (int j = i+1; j < n; j++) {
12                 if (less(a[j], a[min])) min = j;
13             }
14             exch(a, i, min);
15             assert isSorted(a, 0, i);
16         }
17         assert isSorted(a);
18     }
19
20     public static void sort(Object[] a, Comparator comparator) {
21         int n = a.length;
22         for (int i = 0; i < n; i++) {
23             int min = i;
24             for (int j = i+1; j < n; j++) {
25                 if (less(comparator, a[j], a[min])) min = j;
26             }
27             exch(a, i, min);
28             assert isSorted(a, comparator, 0, i);
29         }
30         assert isSorted(a, comparator);
31     }
32
33     // is v < w ?
34     private static boolean less(Comparable v, Comparable w) {
35         return v.compareTo(w) < 0;
36     }
37
38     // is v < w ?
39     private static boolean less(Comparator comparator, Object v, Object w) {
40         return comparator.compare(v, w) < 0;
41     }
42
43     // exchange a[i] and a[j]
44     private static void exch(Object[] a, int i, int j) {
45         Object swap = a[i];
46         a[i] = a[j];
47         a[j] = swap;
48     }
49
50     // is the array a[] sorted?
51     private static boolean isSorted(Comparable[] a) {
52         return isSorted(a, 0, a.length - 1);
53     }
54
55     // is the array sorted from a[lo] to a[hi]
56     private static boolean isSorted(Comparable[] a, int lo, int hi) {
57         for (int i = lo + 1; i <= hi; i++)
58             if (less(a[i], a[i-1])) return false;
59         return true;
60     }
61
62     // is the array a[] sorted?
63     private static boolean isSorted(Object[] a, Comparator comparator) {
64         return isSorted(a, comparator, 0, a.length - 1);
65     }
66
67     // is the array sorted from a[lo] to a[hi]
68     private static boolean isSorted(Object[] a, Comparator comparator, int lo, int hi) {
69         for (int i = lo + 1; i <= hi; i++)
70             if (less(comparator, a[i], a[i-1])) return false;
71         return true;
72     }
73
74     // print array to standard output
75     private static void show(Comparable[] a) {
76         for (int i = 0; i < a.length; i++) {
77             StdOut.println(a[i]);
78         }
79     }
80 }

1.3 选择排序算法性能分析

  • 对于长度为N的数组,选择排序需要大约(N-1)+(N-2)+...+2+1=N(N-1)/2~N2/2次比较和N次交换;
  • 运行时间和输入无关;
  • 数据移动是最少的;
  • 算法不稳定。

2. 插入排序介绍

2.1 插入排序算法流程

Step1:从第一个元素开始,该元素可以认为已经被排序;
Step2:取出下一个元素,在已经排序的元素序列中从后向前扫描;
Step3:如果该元素(已排序)大于新元素,将该元素移到下一位置;
Step4:重复Step3,直到找到已排序的元素小于或者等于新元素的位置;
Step5:将新元素插入到该位置后;
Step6:重复步骤Step2~Step5.

图2 插入排序的轨迹

2.2 插入排序算法代码实现

  1 import java.util.Comparator;
  2
  3 public class Insertion {
  4
  5     // This class should not be instantiated.
  6     private Insertion() { }
  7
  8     public static void sort(Comparable[] a) {
  9         int n = a.length;
 10         for (int i = 0; i < n; i++) {
 11             for (int j = i; j > 0 && less(a[j], a[j-1]); j--) {
 12                 exch(a, j, j-1);
 13             }
 14             assert isSorted(a, 0, i);
 15         }
 16         assert isSorted(a);
 17     }
 18
 19     public static void sort(Comparable[] a, int lo, int hi) {
 20         for (int i = lo; i <= hi; i++) {
 21             for (int j = i; j > lo && less(a[j], a[j-1]); j--) {
 22                 exch(a, j, j-1);
 23             }
 24         }
 25         assert isSorted(a, lo, hi);
 26     }
 27
 28
 29     public static void sort(Object[] a, Comparator comparator) {
 30         int n = a.length;
 31         for (int i = 0; i < n; i++) {
 32             for (int j = i; j > 0 && less(a[j], a[j-1], comparator); j--) {
 33                 exch(a, j, j-1);
 34             }
 35             assert isSorted(a, 0, i, comparator);
 36         }
 37         assert isSorted(a, comparator);
 38     }
 39
 40     public static void sort(Object[] a, int lo, int hi, Comparator comparator) {
 41         for (int i = lo; i <= hi; i++) {
 42             for (int j = i; j > lo && less(a[j], a[j-1], comparator); j--) {
 43                 exch(a, j, j-1);
 44             }
 45         }
 46         assert isSorted(a, lo, hi, comparator);
 47     }
 48
 49
 50     public static int[] indexSort(Comparable[] a) {
 51         int n = a.length;
 52         int[] index = new int[n];
 53         for (int i = 0; i < n; i++)
 54             index[i] = i;
 55
 56         for (int i = 0; i < n; i++)
 57             for (int j = i; j > 0 && less(a[index[j]], a[index[j-1]]); j--)
 58                 exch(index, j, j-1);
 59
 60         return index;
 61     }
 62
 63     // is v < w ?
 64     private static boolean less(Comparable v, Comparable w) {
 65         return v.compareTo(w) < 0;
 66     }
 67
 68     // is v < w ?
 69     private static boolean less(Object v, Object w, Comparator comparator) {
 70         return comparator.compare(v, w) < 0;
 71     }
 72
 73     // exchange a[i] and a[j]
 74     private static void exch(Object[] a, int i, int j) {
 75         Object swap = a[i];
 76         a[i] = a[j];
 77         a[j] = swap;
 78     }
 79
 80     // exchange a[i] and a[j]  (for indirect sort)
 81     private static void exch(int[] a, int i, int j) {
 82         int swap = a[i];
 83         a[i] = a[j];
 84         a[j] = swap;
 85     }
 86
 87     private static boolean isSorted(Comparable[] a) {
 88         return isSorted(a, 0, a.length - 1);
 89     }
 90
 91     // is the array sorted from a[lo] to a[hi]
 92     private static boolean isSorted(Comparable[] a, int lo, int hi) {
 93         for (int i = lo+1; i <= hi; i++)
 94             if (less(a[i], a[i-1])) return false;
 95         return true;
 96     }
 97
 98     private static boolean isSorted(Object[] a, Comparator comparator) {
 99         return isSorted(a, 0, a.length - 1, comparator);
100     }
101
102     // is the array sorted from a[lo] to a[hi]
103     private static boolean isSorted(Object[] a, int lo, int hi, Comparator comparator) {
104         for (int i = lo + 1; i <= hi; i++)
105             if (less(a[i], a[i-1], comparator)) return false;
106         return true;
107     }
108
109    // print array to standard output
110     private static void show(Comparable[] a) {
111         for (int i = 0; i < a.length; i++) {
112             StdOut.println(a[i]);
113         }
114     }
115 }

2.3 插入排序算法性能分析

  • 对于长度为N且主键不重复的数组,平均情况下需要~N2/4次比较和~N2/4次交换,最坏情况下(逆序数组)需要~N2/2次比较和~N2/2次交换,最好情况下(数组已经有序)需要~N-1次比较和0次交换;
  • 比较的总次数总是在交换的总次数上加一个额外项,该项为N减去被插入的元素正好是已知排序中的最小元素的次数;
  • 插入排序算法适用于部分有序的数组:1)数组中每个元素的距离离它的终点位置都不远;2)一个有序的大数组接一个小数组;3)数组中只有几个元素的位置不确定;
  • 算法稳定。

3. 希尔排序介绍

希尔(Shell)排序又称为缩小增量排序,它是一种插入排序。它是直接插入排序算法的一种威力加强版。

3.1 希尔排序算法流程

把记录按步长 gap 分组,对每组记录采用直接插入排序方法进行排序。
随着步长逐渐减小,所分成的组包含的记录越来越多,当步长的值减小到 1 时,整个数据合成为一组,构成一组有序记录,则完成排序。

图3 希尔排序的轨迹

3.2 希尔排序算法代码实现

 1 public class Shell {
 2
 3     // This class should not be instantiated.
 4     private Shell() { }
 5
 6     public static void sort(Comparable[] a) {
 7         int n = a.length;
 8
 9         // 3x+1 increment sequence:  1, 4, 13, 40, 121, 364, 1093, ...
10         int h = 1;
11         while (h < n/3) h = 3*h + 1;
12
13         while (h >= 1) {
14             // h-sort the array
15             for (int i = h; i < n; i++) {
16                 for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) {
17                     exch(a, j, j-h);
18                 }
19             }
20             assert isHsorted(a, h);
21             h /= 3;
22         }
23         assert isSorted(a);
24     }
25
26     // is v < w ?
27     private static boolean less(Comparable v, Comparable w) {
28         return v.compareTo(w) < 0;
29     }
30
31     // exchange a[i] and a[j]
32     private static void exch(Object[] a, int i, int j) {
33         Object swap = a[i];
34         a[i] = a[j];
35         a[j] = swap;
36     }
37
38     private static boolean isSorted(Comparable[] a) {
39         for (int i = 1; i < a.length; i++)
40             if (less(a[i], a[i-1])) return false;
41         return true;
42     }
43
44     // is the array h-sorted?
45     private static boolean isHsorted(Comparable[] a, int h) {
46         for (int i = h; i < a.length; i++)
47             if (less(a[i], a[i-h])) return false;
48         return true;
49     }
50
51     // print array to standard output
52     private static void show(Comparable[] a) {
53         for (int i = 0; i < a.length; i++) {
54             StdOut.println(a[i]);
55         }
56     }
57 }

3.3 希尔排序算法性能分析

  • 对于长度为N且主键不重复的数组,平均情况下需要~NlgN次比较,最坏情况需要~N1.5次比较;
  • 目前最好的排序序列是1,5,19,41,109...,由Sedgewick提出;
  • 希尔排序算法属于插入排序,但是不稳定。

三、一种洗牌方法的实现(直接上代码)

public class StdRandom
{// 这是一个随机数静态方法库,包含各种随机数生成方法和随机数操作方法
...public static void shuffle(int[] a) {// 参数可以改成其他数据类型doubleif (a == null) throw new IllegalArgumentException("argument array is null");int n = a.length;for (int i = 0; i < n; i++) {int r = i + StdRandom.uniform(n-i);       //StdRandom.uniform(n-i) 方法随机产生1到n-i之间的整数int temp = a[i];a[i] = a[r];a[r] = temp;}}
}

作者: 邹珍珍(Pearl_zhen)

出处: http://www.cnblogs.com/zouzz/

声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接 如有问题, 可邮件(zouzhenzhen@seu.edu.cn)咨询.

转载于:https://www.cnblogs.com/zouzz/p/6095345.html

排序---初级排序算法(选择排序、插入排序和希尔排序)相关推荐

  1. 十大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序

    冒泡排序.选择排序.插入排序.希尔排序.归并排序.快速排序.堆排序.计数排序.桶排序.基数排序的动图与源代码. 目录 关于时间复杂度 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 ...

  2. 数据结构与算法笔记(九)—— 希尔排序

    什么是希尔排序 希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法. 该方法因DL.Shell于1959年提出而得名 ...

  3. 【Java数据结构与算法】第七章 冒泡排序、选择排序、插入排序和希尔排序

    第七章 冒泡排序.选择排序.插入排序和希尔排序 文章目录 第七章 冒泡排序.选择排序.插入排序和希尔排序 一.冒泡排序 1.基本介绍 2.代码实现 二.选择排序 1.基本介绍 2.代码实现 三.插入排 ...

  4. 数据结构—排序算法总结(插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、合并排序、计数排序)

    *排序 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作. 稳定性 在待排序的数组中,如果出现多个相同的关键字,例如:98751555512,中出现重复的数字,在 ...

  5. 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)...

    写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...

  6. 排序算法(分类,时间复杂度)(快速排序,插入排序,希尔排序,选择排序,冒泡排序)

    1.排序算法 1.排序的分类 分为内部排序和外部排序,其中内部排序分为插入排序.选择排序.交换排序.归并排序和基数排序.插入排序包括直接插入排序和希尔排序:选择排序包括简单选择排序和堆排序:交换排序包 ...

  7. 排序算法(冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序、基数排序)

    排序也叫排序算法,排序是将一组数据,依指定的顺序进行排列的过程. 排序的分类: 1)内部排序:指将需要处理的所有数据都加载到内部存储器中进行排序. 2)外部排序:数据量过大,无法全部加载到内存中,需要 ...

  8. 10种排序算法比较(直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序、折半插入排序、2路插入排序)

    本文(所有排序算法代码+综合比较代码)链接:https://download.csdn.net/download/qq_39932172/11217572 一.比较目的: 由于<数据结构> ...

  9. JS 排序算法详解(冒泡排序,选择排序,插入排序,希尔排序,快速排序)

    JS 排序算法详解(冒泡排序,选择排序,插入排序,希尔排序,快速排序) 一. 大O表示法 在进行排序算法之前,我们得先掌握一种对算法效率的表示方法,大O表示法. 我们使用大O表示法来表示算法的时间复杂 ...

最新文章

  1. Deep learning的一些教程 (转载)
  2. kettle 内存设置_Kettle性能调优汇总
  3. EmbarassedBirds全体开发人员落泪
  4. 转发和重定向又是什么“垃圾”——教你再分类
  5. FISCO BCOS流量控制实现
  6. poj 1328 贪心+qsort
  7. html的基本标记符,html的基本标记符号
  8. binary 和 varbinary 用法全解
  9. linux下的pdf工具下载,Linux系统下的PDF好帮手 LinuxPDFeditor
  10. 阿里云上云迁移工具案例实践:腾讯云迁移到阿里云
  11. python调用foxmail 发邮件_foxmail 收取已发送邮件
  12. iOS调用系统相机、相册里面的文字显示英文
  13. 单元測试中 Right-BICEP 和 CORRECT
  14. 芯片短缺局势依然严峻,供应链上下该如何破局?
  15. 淘宝电商产品jQuery图片放大镜代码
  16. qq音乐sign算法还原源码放送及jsvmp全流程分析
  17. 微信支付宝支付如何盈利?盈利如何?
  18. 嵌入式系统分析与设计
  19. Unity3D-实战-01坦克大战-day03箱式对撞机、钢体、2D渲染层级问题、重力问题(出现坠落现象)、旋转问题、左右上下冲突问题、抖动问题
  20. 【Linux上安装Scala】

热门文章

  1. 替换libc中的内存分配函数
  2. Android---Android 屏幕尺寸与密度
  3. DELL Poweredge服务器安装操作系统指南 补全之磁盘驱动制作
  4. 按需生产 ,我们准备好了吗?
  5. windows创建定时任务执行python脚本
  6. 关于python mysql
  7. curl抓取页面时遇到重定向的解决方法(转)
  8. 深入理解 Neutron -- OpenStack 网络实现(2):VLAN 模式
  9. 亚马逊AWS:正确设置FTP
  10. 学习 Java 8 - 函数式接口 Lambda