基于比较实现的七大排序算法:
思维导图记录:
测评排序算法的重要指标:稳定性
稳定性:两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算法是具备稳定性的排序 算法。
源码测试实现:
Lab.java
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Random;
interface SortMethod {
String getName();
void sort(int[] a);
}
class InsertSortMethod implements SortMethod {
@Override
public String getName() {
return "插入排序";
}
@Override
public void sort(int[] a) {
Sort.insertSort0(a);
}
}
class shellSortMethod implements SortMethod{
@Override
public String getName() {
return "希尔排序";
}
@Override
public void sort(int[] a) {
Sort.shellSort(a);
}
}
class selectSort0Method implements SortMethod{
@Override
public String getName() {
return "选择排序";
}
@Override
public void sort(int[] a) {
Sort.selectSort0(a);
}
}
class heapSortMethod implements SortMethod{
@Override
public String getName() {
return "堆排";
}
@Override
public void sort(int[] a) {
Sort.heapSort(a);
}
}
class bubbleSortMethod implements SortMethod{
@Override
public String getName() {
return "冒泡排序";
}
@Override
public void sort(int[] a) {
Sort.bubbleSort(a);
}
}
public class Lab {
private static SortMethod[] methods = {
new InsertSortMethod(),
};
private static SortMethod[] methods1 = {
new shellSortMethod(),
};
private static SortMethod[] methods2 = {
new selectSort0Method(),
};
private static SortMethod[] methods3 = {
new heapSortMethod(),
};
private static SortMethod[] methods4 = {
new bubbleSortMethod(),
};
//随机
public static int[] buildRandom(int n) {
Random random = new Random(20190924);
int[] r = new int[n];
for (int i = 0; i < n; i++) {
r[i] = random.nextInt(n);
}
return r;
}
//有序
public static int[] buildSorted(int n) {
Random random = new Random(20190924);
int[] r = new int[n];
for (int i = 0; i < n; i++) {
r[i] = random.nextInt(n);
}
Arrays.sort(r);
return r;
}
//逆序
private static void shellSortR(int[] array) {
int gap = array.length;
while (true) {
gap = (gap / 3) + 1;
//gap = gap / 2;
insertSortWithGapR(array, gap);
if (gap == 1) {
break;
}
}
}
private static void insertSortWithGapR(int[] array, int gap) {
for (int i = gap; i < array.length; i++) {
int key = array[i];
int j;
for (j = i - gap; j >= 0 && array[j] < key; j -= gap) {
array[j + gap] = array[j];
}
array[j + gap] = key;
}
}
public static int[] buildReversed(int n) {
Random random = new Random(20190924);
int[] r = new int[n];
for (int i = 0; i < n; i++) {
r[i] = random.nextInt(n);
}
shellSortR(r);
return r;
}
//相等
public static int[] buildEquals(int n) {
return new int[n];
}
public static void main(String[] args) {
for (int i = 1; i <= 4; i++) {
int n = i * 50000;
int[] random = buildRandom(n);
int[] sorted = buildSorted(n);
int[] reversed = buildReversed(n);
int[] equals = buildEquals(n);
// //插入排序随机数据测试
// for (SortMethod method : methods) {
// int[] a = random.clone();
// long begin = System.nanoTime();
// method.sort(a);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("随机情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //插入排序顺序数据测试
// for (SortMethod method : methods) {
// int[] b = sorted.clone();
// long begin = System.nanoTime();
// method.sort(b);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("有序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //插入排序逆序数据测试
// for (SortMethod method : methods) {
// int[] c = reversed.clone();
// long begin = System.nanoTime();
// method.sort(c);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("逆序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //插入排序相等数据测试
// for (SortMethod method : methods) {
// int[] d = equals.clone();
// long begin = System.nanoTime();
// method.sort(d);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("相等情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
//
// //希尔排序随机数据测试
// for (SortMethod method : methods1) {
// int[] a = random.clone();
// long begin = System.nanoTime();
// method.sort(a);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("随机情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //希尔排序顺序数据测试
// for (SortMethod method : methods1) {
// int[] b = sorted.clone();
// long begin = System.nanoTime();
// method.sort(b);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("有序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //希尔排序逆序数据测试
// for (SortMethod method : methods1) {
// int[] c = reversed.clone();
// long begin = System.nanoTime();
// method.sort(c);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("逆序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //希尔排序相等数据测试
// for (SortMethod method : methods1) {
// int[] d = equals.clone();
// long begin = System.nanoTime();
// method.sort(d);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("相等情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
// //选择排序测试
// //选择排序随机数据测试
// for (SortMethod method : methods2) {
// int[] a = random.clone();
// long begin = System.nanoTime();
// method.sort(a);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("随机情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //选择排序顺序数据测试
// for (SortMethod method : methods2) {
// int[] b = sorted.clone();
// long begin = System.nanoTime();
// method.sort(b);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("有序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //选择排序逆序数据测试
// for (SortMethod method : methods2) {
// int[] c = reversed.clone();
// long begin = System.nanoTime();
// method.sort(c);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("逆序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //选择排序相等数据测试
// for (SortMethod method : methods2) {
// int[] d = equals.clone();
// long begin = System.nanoTime();
// method.sort(d);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("相等情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //堆排序测试
// //堆排序随机数据测试
// for (SortMethod method : methods3) {
// int[] a = random.clone();
// long begin = System.nanoTime();
// method.sort(a);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("随机情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //堆排序顺序数据测试
// for (SortMethod method : methods3) {
// int[] b = sorted.clone();
// long begin = System.nanoTime();
// method.sort(b);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("有序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //堆排序逆序数据测试
// for (SortMethod method : methods3) {
// int[] c = reversed.clone();
// long begin = System.nanoTime();
// method.sort(c);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("逆序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//
// //堆排序相等数据测试
// for (SortMethod method : methods3) {
// int[] d = equals.clone();
// long begin = System.nanoTime();
// method.sort(d);
// long end = System.nanoTime();
// double ms = (end - begin) * 1.0 / 1000000;
//
// System.out.printf("相等情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
// }
//冒泡排序测试
//冒泡排序随机数据测试
for (SortMethod method : methods4) {
int[] a = random.clone();
long begin = System.nanoTime();
method.sort(a);
long end = System.nanoTime();
double ms = (end - begin) * 1.0 / 1000000;
System.out.printf("随机情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
}
//冒泡排序顺序数据测试
for (SortMethod method : methods4) {
int[] b = sorted.clone();
long begin = System.nanoTime();
method.sort(b);
long end = System.nanoTime();
double ms = (end - begin) * 1.0 / 1000000;
System.out.printf("有序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
}
//冒泡排序逆序数据测试
for (SortMethod method : methods4) {
int[] c = reversed.clone();
long begin = System.nanoTime();
method.sort(c);
long end = System.nanoTime();
double ms = (end - begin) * 1.0 / 1000000;
System.out.printf("逆序情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
}
//冒泡排序相等数据测试
for (SortMethod method : methods4) {
int[] d = equals.clone();
long begin = System.nanoTime();
method.sort(d);
long end = System.nanoTime();
double ms = (end - begin) * 1.0 / 1000000;
System.out.printf("相等情况下%s个数据: %s: 耗时 %.5f 毫秒%n", n,method.getName(), ms);
}
}
}
public static SortMethod[] getMethods() {
return methods;
}
public static void setMethods(SortMethod[] methods) {
Lab.methods = methods;
}
}
Sort.java
import java.util.Arrays;
import java.util.Random;
public class Sort {
// 直接插入排序
// public static void insertSort(int[] array) {
// for (int i = 1; i < array.length; i++) {
// // 有序 [0, i)
// // 无序 [i, array.length)
// int key = array[i];
// int j;
// for (j = i - 1; j >= 0; j--) {
// if (array[j] <= key) {
// break;
// } else {
// array[j + 1] = array[j];
// }
// }
// array[j + 1] = key;
// }
// }
/**
* 时间复杂度
* 最好 平均 最坏
* O(n) O(n^2) O(n^2
* 数据有序 数据逆序
* 空间复杂度
* O(1)
* @param array
*/
//直接插入排序
public static void insertSort0(int[] array) {
for (int i = 1; i < array.length; i++) {
// 有序 [0, i)
// 无序 [i, array.length)
int key = array[i];
int j;
for (j = i - 1; j >= 0 && array[j] > key; j--) {
array[j + 1] = array[j];
}
array[j + 1] = key;
}
}
//希尔排序
public static void shellSort(int[] array) {
int gap = array.length;
while (true) {
gap = (gap / 3) + 1;
//gap = gap / 2;
insertSortWithGap(array, gap);
if (gap == 1) {
break;
}
}
}
private static void insertSortWithGap(int[] array, int gap) {
for (int i = gap; i < array.length; i++) {
int key = array[i];
int j;
for (j = i - gap; j >= 0 && array[j] > key; j -= gap) {
array[j + gap] = array[j];
}
array[j + gap] = key;
}
}
//选择排序
public static void selectSort0(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
// 无序区间 [i, array.length)
int minIndex = i;
for (int j = i + 1; j < array.length; j++) {
if (array[j] < array[minIndex]) {
minIndex = j;
}
}
swap(array, minIndex, i);
}
}
public static void selectSort2(int[] array) {
// 无序: [begin, end]
int begin = 0;
int end = array.length - 1;
while (begin < end) {
int minIndex = begin;
int maxIndex = begin;
for (int j = begin + 1; j <= end; j++) {
if (array[j] < array[minIndex]) {
minIndex = j;
}
if (array[j] > array[maxIndex]) {
maxIndex = j;
}
}
swap(array, minIndex, begin);
if (maxIndex == begin) {
maxIndex = minIndex;
}
swap(array, maxIndex, end);
begin++; end--;
}
}
public static void selectSort(int[] array) {
// 每次选最大的放到无序区间的最后
for (int i = 0; i < array.length - 1; i++) {
// 无序 [0, array.length - i)
// 有序 [array.length - i, array.length)
int maxIndex = 0;
for (int j = 1; j < array.length - i; j++) {
if (array[j] > array[maxIndex]) {
maxIndex = j;
}
}
swap(array, maxIndex, array.length - i - 1);
}
}
private static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
public static void main(String[] args) {
testRight();
testSpeed();
}
public static void heapSort(int[] array) {
createHeapBig(array);
for (int i = 0; i < array.length - 1; i++) {
// 无序 [0, array.length - i)
// 交换 array[0], array[length - i - 1]
// 无序 [0, array.length - i - 1)
// 无序长度 array.length - i - 1
// 下标 0 进行向下调整
swap(array, 0, array.length - i - 1);
shiftDownBig(array, 0, array.length - i - 1);
}
}
private static void createHeapBig(int[] array) {
for (int i = (array.length - 2) / 2; i >= 0; i--) {
shiftDownBig(array, i, array.length);
}
}
private static void shiftDownBig(int[] array, int i, int size) {
while (2 * i + 1 < size) {
int max = 2 * i + 1;
if (max + 1 < size && array[max+1] > array[max]) {
max = max + 1;
}
if (array[i] >= array[max]) {
return;
}
swap(array, i, max);
i = max;
}
}
public static void bubbleSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
boolean isSort = true;
for (int j = 0; j < array.length - i - 1; j++) {
if (array[j] > array[j + 1]) {
swap(array, j, j + 1);
isSort = false;
}
}
if (isSort) {
return;
}
}
}
public static void testRight() {
int[] a = { 2, 3, 7, 9, 4, 5, 6, 9, 1, 4, 7, 8 };
int[] b = a.clone();
bubbleSort(b);
System.out.println(Arrays.toString(b));
int[] c = a.clone();
Arrays.sort(c);
System.out.println(Arrays.toString(c));
System.out.println(Arrays.equals(b, c));
}
public static void testSpeed() {
Random random = new Random(20190924);
int[] a = new int[10 * 10000];
for (int i = 0; i < 10 * 10000; i++) {
a[i] = random.nextInt(10 * 10000);
}
long begin = System.nanoTime();
bubbleSort(a);
long end = System.nanoTime();
double ms = (end - begin) * 1.0 / 1000 / 1000;
System.out.printf("一共耗时: %.5f 毫秒%n", ms);
}
}
测评结果:
随机数据,有序数据,逆序数据,相等数据(50000,100000,150000,200000个数据测评完成时间)
A,插入排序
B,希尔排序
C,选择排序
D,堆排序
E,冒泡排序
F,归并排序测试有误,明天更新