一.jdk中自带的排序
1.数据的排序Arrays.sort()
方法
该方法根据Comparable接口中实现的compareTo()方法进行排序依据
@Test
public void testArraysSort() {
int[] arr = new int[] { 7, 2, 9, 4, 8, 3, 0 };
System.out.print("排序前:");
printArr(arr);
Arrays.sort(arr);
System.out.print("排序后:");
printArr(arr);
}
private static void printArr(int[] arr) {
System.out.print("[");
for (int i : arr) {
System.out.print(i);
System.out.print(",");
}
System.out.println("]");
}
2.Collections.sort(List<T> list)
方法
该方法需要List集合中的元素实现Comparable接口(<T extends Comparable<? super T>>
)。
@Test
public void testCollectionsSort(){
List<Integer> list = new ArrayList<Integer>();
list.add(6);
list.add(1);
list.add(9);
list.add(7);
list.add(3);
System.out.println("排序前:"+list);
Collections.sort(list);
System.out.println("排序后 :"+list);
}
该方法底层是先将List集合转为数据后再通过Arrays.sort()
方法进行排序。
方法源码:
public static <T extends Comparable<? super T>> void sort(List<T> list) {
Object[] a = list.toArray();
Arrays.sort(a);
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}
3.HashSet的排序
HashSet通过对象的hashCode方法的返回值进行排序
对象
class HashSetSort{
private int id;
private String name;
//省略getter,setter方法
public HashSetSort(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public int hashCode() {
return id;
}
@Override
public String toString() {
return "name=" + name + "";
}
}
测试方法
@Test
public void testSetSort(){
Set<Object> set = new HashSet<Object>();
set.add(new HashSetSort(3, "a3"));
set.add(new HashSetSort(2, "a2"));
set.add(new HashSetSort(4, "a4"));
set.add(new HashSetSort(5, "a5"));
set.add(new HashSetSort(1, "a1"));
System.out.println(set);//[name=a, name=b, name=c, name=d, name=e]
}
二.自定义排序
通用方法
该方法用于输出数据的数据
private static void printArr(int[] arr) {
StringBuffer sb = new StringBuffer();
sb.append("[");
for (int i : arr) {
sb.append(i);
sb.append(",");
}
sb.deleteCharAt(sb.length() - 1).append("]");
System.out.println(sb);
}
1.冒泡排序
思路:
从第一个元素开始如果第一个元素大于第二个元素,则交换位置,然后对比第二个元素与第三个元素,如果第二个元素大于第三个元素则交换位置,一次轮对比到最后一个元素的位置,第一次冒泡完成,获取到了最大值。第二轮则对比到倒数第二个元素,获取到第二大的值。以此类推,直到排序完成。
测试代码:
@Test
public void bubbleSort() {
int[] arr = new int[] { 4, 3, 5, 1, 2 };
// i表示轮数,因为每轮会查询出一个最大值,第i轮能查询出i个最大值,而只要确定了(i-1)个最大值,剩下的那个自然就是最小值,无需再判断,所以有总共需要(arr.length-1)轮
for (int i = 0; i < arr.length - 1; i++) {
//j表示需要比较到的最大索引数,因为第i轮会确定i个最大值,所以每轮为(arr.length-当前轮数)
for (int j = 0; j + 1 < arr.length - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
System.out.print(String.format("第%d轮%d次排序结果为:", i + 1, j + 1));
printArr(arr);
}
System.out.print(String.format("***第%d轮排序完后顺序为:", i + 1));
printArr(arr);
}
}
测试结果:
第1轮1次排序结果为:[3,4,5,1,2]
第1轮2次排序结果为:[3,4,5,1,2]
第1轮3次排序结果为:[3,4,1,5,2]
第1轮4次排序结果为:[3,4,1,2,5]
***第1轮排序完后顺序为:[3,4,1,2,5]
第2轮1次排序结果为:[3,4,1,2,5]
第2轮2次排序结果为:[3,1,4,2,5]
第2轮3次排序结果为:[3,1,2,4,5]
***第2轮排序完后顺序为:[3,1,2,4,5]
第3轮1次排序结果为:[1,3,2,4,5]
第3轮2次排序结果为:[1,2,3,4,5]
***第3轮排序完后顺序为:[1,2,3,4,5]
第4轮1次排序结果为:[1,2,3,4,5]
***第4轮排序完后顺序为:[1,2,3,4,5]
2.选择排序
思路
它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
选择排序的主要优点与数据移动有关。如果某个元素位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素,它们当中至少有一个将被移到其最终位置上,因此对n个元素的表进行排序总共进行至多n-1次交换。在所有的完全依靠交换去移动元素的排序方法中,选择排序属于非常好的一种。
测试方法:
@Test
public void selectionSort() {
int[] arr = new int[] { 4, 3, 5, 1, 2 };
// i表示轮数,因为每轮会查询出一个最大值,第i轮能查询出i个最小值,而只要确定了(i-1)个最小值,剩下的那个自然就是最大值,无需再判断,所以有总共需要(arr.length-1)轮
for (int i = 0; i < arr.length - 1; i++) {
// 记录最小值的索引(默认是当前轮的第一个值)
int minIndex = i;
System.out.println(String.format("开始第%d轮,默认最小值为%d", i + 1, arr[minIndex]));
// 判断最小值与之后每个值得大小
for (int j = i + 1; j < arr.length; j++) {
// 如果遍历到的值小于此时记录的最小值,则重新制定最小值的索引为当前遍历到的值得索引
if (arr[j] < arr[minIndex]) {
System.out.println(String.format("发现了有更小的值,当前记录的最小值为%d,遍历到的值为%d",
arr[minIndex], arr[j]));
minIndex = j;
}
}
//
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
System.out.print(String.format("***第%d轮排序完后顺序为:", i + 1));
printArr(arr);
}
}
测试结果:
开始第1轮,默认最小值为4
发现了有更小的值,当前记录的最小值为4,遍历到的值为3,最小值的索引为1
发现了有更小的值,当前记录的最小值为3,遍历到的值为1,最小值的索引为3
***第1轮排序完后顺序为:[1,3,5,4,2]
开始第2轮,默认最小值为3
发现了有更小的值,当前记录的最小值为3,遍历到的值为2,最小值的索引为4
***第2轮排序完后顺序为:[1,2,5,4,3]
开始第3轮,默认最小值为5
发现了有更小的值,当前记录的最小值为5,遍历到的值为4,最小值的索引为3
发现了有更小的值,当前记录的最小值为4,遍历到的值为3,最小值的索引为4
***第3轮排序完后顺序为:[1,2,3,4,5]
开始第4轮,默认最小值为4
***第4轮排序完后顺序为:[1,2,3,4,5]
3.插入排序
思路:
它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
测试代码:
@Test
public void insertionSort() {
int[] arr = new int[] { 4, 3, 5, 1, 2 };
for (int i = 0; i < arr.length - 1; i++) {
// 取出已排序好的子数组后的第一个元素
int temp = arr[i + 1];
// num为每轮的第n次比较,仅用于查看每次比较的的结果,对排序结果无影响
// j为默认已经排序完的子数组的最后一个元素的索引
for (int j = i, num = 1; j >= 0; j--, num++) {
if (temp > arr[j]) {
//如果取出值大于比较值,索引排序已完成,进行下一轮排序
break;
}
//如果取出值小于比较值,索引比较值要往后移动
arr[j + 1] = arr[j];
arr[j] = temp;
System.out.print(String.format("第%d轮%d次比较完后顺序为:", i + 1, num));
printArr(arr);
}
System.out.print(String.format("***第%d轮排序完后顺序为:", i + 1));
printArr(arr);
}
}
测试结果:
第1轮1次比较完后顺序为:[3,4,5,1,2]
***第1轮排序完后顺序为:[3,4,5,1,2]
***第2轮排序完后顺序为:[3,4,5,1,2]
第3轮1次比较完后顺序为:[3,4,1,5,2]
第3轮2次比较完后顺序为:[3,1,4,5,2]
第3轮3次比较完后顺序为:[1,3,4,5,2]
***第3轮排序完后顺序为:[1,3,4,5,2]
第4轮1次比较完后顺序为:[1,3,4,2,5]
第4轮2次比较完后顺序为:[1,3,2,4,5]
第4轮3次比较完后顺序为:[1,2,3,4,5]
***第4轮排序完后顺序为:[1,2,3,4,5]