简单排序
Comparable接口
Java提供了Comparable就是用来定义排序规则的。
例:
- 定义一个学生类Student,具体年龄age和姓名username两个属性,并通过Comparable接口提供比较规则;
定义测试类Test,在测试类Test中定义测试方法Comparable getMax(Comparable c1, Comparable c2)完成测试。
1 | public class Student implements Comparable<Student>{ |
1 | public class Test{ |
冒泡排序
需求:
- 排序前:{4,5,6,3,2,1}
- 排序后:{1,2,3,4,5,6}
排序原理:
- 比较相邻的元素,如果前一个元素比后一个元素大,就交换这两个元素的位置;
- 对每一对相邻元素做同样的工作,从开始第一对元素到结尾的最后一对元素。最终最后位置的元素就是最大值。
冒泡次数 | 冒泡后的结果 |
---|---|
初始状态 | 4,5,6,3,2,1 |
第一次冒泡 | 4,5,3,2,1,6 |
第二次冒泡 | 4,3,2,1,5,6 |
第三次冒泡 | 3,2,1,4,5,6 |
第四次冒泡 | 2,1,3,4,5,6 |
第五次冒泡 | 1,2,3,4,5,6 |
第六次冒泡 | 1,2,3,4,5,6 |
冒泡排序API设计:
类名 | Bubble |
---|---|
构造方法 | Bubble() |
成员方法 | public static void sort(Comparable[] a):对数组内的元素进行排序 |
private static boolean greater(Comparable v, Comparable w):判断v是否大于w | |
private static void exch(Comparable[] a, int i, int j):交换a数组中,索引i和索引j处的值 |
冒泡排序的代码实现:
1 | public class Bubble{ |
1 | public class BubbleTest{ |
冒泡排序的时间复杂度分析
在最坏情况下,也就是假如要排序的元素为{6,5,4,3,2,1},那么元素的比较次数为:$(N-1)+(N-2)…+2+1=(1+N-1)*(N-1)/2=\frac{N^2-N}{2}$元素交换次数为:$\frac{N^2-N}{2}$,总执行次数为$N^2-N$,按照大O推导法则,冒泡排序的时间复杂度为$O(N^2)$。
选择排序
需求:
- 排序前:{4,6,8,7,9,2,10,1}
- 排序后:{1,2,4,5,7,8,9,10}
排序原理:
- 每一次遍历的过程中,都假定第一个索引处的元素是最小值,和其他索引处的值依次进行比较,如果当前索引处的值大于其他某个索引处的值,则假定其他某个索引处的值为最小值,最后可以找到最小值所在的索引
- 交换第一个索引处和最小值所在的索引处的值
{4,6,8,7,9,2,10,1} | 原始数据 |
---|---|
{1,6,8,7,9,2,10,4} | 第一趟排序Min=1 |
{1,2,8,7,9,6,10,4} | 第二趟排序Min=2 |
{1,2,4,7,9,6,10,8} | 第三趟排序Min=4 |
{1,2,4,6,9,7,10,8} | 第四趟排序Min=6 |
{1,2,4,6,7,9,10,8} | 第五趟排序Min=7 |
{1,2,4,6,7,8,10,9} | 第六趟排序Min=8 |
{1,2,4,6,7,8,9,10} | 第七趟排序Min=9 |
选择排序API设计:
类名 | Selection |
---|---|
构造方法 | Selection() |
成员方法 | public static void sort(Comparable[] a) |
private static boolean greater(Comparable v, Comparable w) | |
private static void exch(Comparable[] a, int i, int j) |
选择排序的代码实现:
1 | public class Selection{ |
1 | public class SelectionTest{ |
选择排序的时间复杂度分析:
数据比较的次数:$(N-1)+(N-2)..+2+1=\frac{N^2-N}{2}$,数据交换次数:N-1,时间复杂度为$O(N^2)$。
插入排序
需求:
- 排序前:{4,3,2,10,12,1,5,6}
- 排序后:{1,2,3,4,5,6,10,12}
排序原理:
- 把所有的元素分为两组,已经排序的未排序的;
- 找到未排序的组中第一个元素,向已排序的组中进行插入;
- 倒叙遍历已经排序的元素,依次和待插入的元素进行比较,直到找到一个元素小于等于待插入元素,那么就把待插入元素放到这个位置,其他的元素向后移动一位。
{4,3,2,10,12,1,5,6} | 原始数据 |
---|---|
{4,3,2,10,12,1,5,6} | 第一趟排序(待插入数字为3) |
{3,4,2,10,12,1,5,6} | 第二趟排序(待插入数字为2) |
{2,3,4,10,12,1,5,6} | 第三趟排序(待插入数字为10) |
{2,3,4,10,12,1,5,6} | 第四趟排序(待插入数字为12) |
{2,3,4,10,12,1,5,6} | 第五趟排序(待插入数字为1) |
{1,2,3,4,10,12,5,6} | 第六趟排序(待插入数字为5) |
{1,2,3,4,5,10,12,6} | 第七趟排序(待插入数字为6) |
{1,2,3,4,5,6,10,12} | 最终结果 |
插入排序API设计:
类名 | Insertion |
---|---|
构造方法 | Insertion() |
成员方法 | public static void sort(Comparable[] a) |
private static boolean greater(Comparable v, Comparable w) | |
private static void exch(Comparable[] a, int i, int j) |
插入排序代码实现:
1 | public class Insertion{ |
1 | public class InsertionTest{ |
插入排序的时间复杂度分析:
在最坏情况下,比较次数为:$(N-1)+(N-2)…+2+1=\frac{N^2-N}{2}$,交换次数为:$\frac{N^2-N}{2}$,执行总次数为:$N^2-N$,因此插入排序的时间复杂度为:$O(N^2)$。