直接进入正题
什么是排序?
排序就是将一组对象按照某种逻辑顺序重新排列的过程
谈到排序必须先聊一下比较器
就 java 而言,有两个比较器接口 Comparable 与 Comparator
Comparable & Comparator 都是用来实现集合中元素的比较、排序的。
两者区别:
Comparable 是在集合内部定义的方法实现的排序,称为内部比较器;Comparator 是在集合外部实现的排序,称为外部比较器。
Comparable 是对象自身实现比较接口,如 String,Integer 等,它们继承了 Comparable 接口,然后实现 comparaTo() 方法,也就是说这些类具有自比较功能,如下方 String 类部分源码所示:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
...
// 实现 comparaTo 方法
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) return c1 - c2;
k++;
}
return len1 - len2;
}
...
}
Comparator 是一个专用的比较器,当对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较
TreeSet<Long> treeSet = new TreeSet<Long>(new Comparator<Long>() {
// 自定义 compare 方法
public int compare(Long o1, Long o2) {
return o1.compareTo(o2);
}
});
使用案例:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class AboutCompara {
public static void main(String[] args) {
// String 类内部实现的 compareTo 方法如下
// public int compareTo(String anotherString) {
// int len1 = value.length;
// int len2 = anotherString.value.length;
// int lim = Math.min(len1, len2);
// char v1[] = value;
// char v2[] = anotherString.value;
//
// int k = 0;
// while (k < lim) {
// char c1 = v1[k];
// char c2 = v2[k];
// if (c1 != c2) {
// return c1 - c2;
// }
// k++;
// }
// return len1 - len2;
// }
// String implement Comparable
String[] arr = { "3", "1", "51", "7", "4" };
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
System.out.println("--------- split line ---------");
List<Integer> list = new ArrayList<Integer>();
list.add(3);
list.add(1);
list.add(5);
list.add(7);
list.add(4);
list.forEach(x -> System.out.print(x + " "));
System.out.println("\n--------- split line ---------");
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return (o1 < o2) ? -1 : ((o1 == o2) ? 0 : 1);
}
});
list.stream().forEach(System.out::println);
}
}
/* 输出如下
[1, 3, 4, 51, 7]
--------- split line ---------
3 1 5 7 4
--------- split line ---------
1
3
4
5
7
*/
初级排序
初级排序实现逻辑较简单,不多做解释,详见下方代码,主要介绍算法实现逻辑以及算法时间复杂度,空间复杂度,算法稳定性1
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* The {@code PrimarySort} class provides static methods for sorting an
* array using selection/bubble/insertion/shell sort.
* @author Floyd
*/
@SuppressWarnings("rawtypes")
public class PrimarySort {
/** Prevents instantiation. */
private PrimarySort() {}
/**
* Selection sort : 算法复杂度O(n^2) 空间复杂度O(1) 不稳
* <p>Rearranges the array in ascending order, using the natural order.
* @param a the array to be sorted
*/
public static void selectionSort(Comparable[] a) {
int n = a.length;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (less(a[j], a[i]))
exch(a, i, j);
}
}
}
/**
* Selection sort 2 : 选择排序2 // 测试了下速度 没什么意义...
*/
public static void selectionSort2(Comparable[] a) {
int n = a.length;
for (int i = 0; i < n / 2; i++) {
int max = i;
for (int j = i + 1; j < n - i; j++) {
if (less(a[j], a[i])) {
exch(a, i, j);
}
if (less(a[max], a[j])) {
max = j;
}
}
exch(a, max, a.length - 1 - i);
}
}
/**
* Bubble sort : 算法复杂度O(n^2) 空间复杂度O(1) 稳
*/
public static void bubbleSort(Comparable[] a) {
int n = a.length;
boolean b;
for (int i = n - 1; i > 0; i--) {
b = true;
for (int j = 0; j < i; j++) {
if (less(a[j + 1], a[j])) {
exch(a, j, j + 1);
b = false;
}
}
if (b) break;
}
}
/**
* Insertion sort : 算法复杂度O(n^2) 空间复杂度O(1) 稳
*/
public static void insertionSort(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);
}
}
}
/**
* The {@code shellSort} fuction provides methods for sorting an
* array using Shell sort with Knuth's increment sequence (1, 4, 13, 40, ...).
* <p>算法复杂度O(n^1.3) 空间复杂度O(1) 不稳
* <p>Knuth's increment sequence
* <p>h = 3 * h + 1
*/
public static void shellSort(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;
}
}
/*
* Helper sorting functions.
*/
/** exchange a[i] and a[j] */
private static void exch(Object[] a, int i, int j) {
Object swap = a[i];
a[i] = a[j];
a[j] = swap;
}
/** is x < y ? */
@SuppressWarnings("unchecked")
private static boolean less(Comparable x, Comparable y) {
return x.compareTo(y) < 0;
}
/** Check if array is sorted - useful for debugging. */
private static boolean isSorted(Comparable[] a) {
for (int i = 1; i < a.length; i++) {
if (less(a[i], a[i - 1]))
return false;
}
return true;
}
@SuppressWarnings("unused")
public static void main(String[] args) {
int num = 10000;
int testTimes = 1;
boolean flag = true;
for (int k = 0; k < testTimes; k++) {
for (int c = 0; ;c++) {
Integer[] arr = new Integer[num];
for (int i = 0; i < num; i++) {
arr[i] = (int) (Math.random() * 100);
}
Date start = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (c == 0) {
System.out.println("Bubble sort");
bubbleSort(arr);
} else if (c == 1) {
System.out.println("Selection sort");
selectionSort(arr);
} else if (c == 2) {
System.out.println("Selection sort 2");
selectionSort2(arr);
} else if (c == 3) {
System.out.println("Insertion sort");
insertionSort(arr);
} else if (c == 4) {
System.out.println("Shell sort");
shellSort(arr);
flag = false;
}
Date end = new Date();
if (isSorted(arr)) {
System.out.println("spend : " + (end.getTime() - start.getTime()) + "ms");
}
if (!flag) break;
}
}
}
}
写于一个睡不着的夜晚~
假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。 ↩︎