排序代码:
/**
* 排序(从小到大)
* 交换排序:简单冒泡排序、常规冒泡排序、优化冒泡排序、快速排序
* 选择排序:简单选择排序、堆排序(时间复杂度:O(nlogn))
* 插入排序:直接插入排序、希尔排序
* 归并排序:递归归并排序、非递归归并排序(时间复杂度:O(nlogn))
*/
public class SortType {
/**
* 最简单的冒泡排序
* (1)外层循环从第一个元素开始往后遍历
* (2)内层循环从外层的值开始往后遍历
* (3)当外层的值大于内层的值时,交换
* 思想:外层每循环一次,都会将数组最小的值放在“第一个”位置
* 时间复杂度:O(n²)
*
* @param arrays 需要排序的数组
*/
public void SimpleBubbleSort(int[] arrays) {
int i, j;
for (i = 0; i < arrays.length; i++) {
for (j = i; j < arrays.length; j++) {
if (arrays[i] > arrays[j]) {
Tools.swap(arrays, i, j);
}
}
}
}
/**
* 常规的冒泡排序
* (1)外层循环从第一个元素开始往后遍历
* (2)内层循环从后往前遍历至值与外层循环相等
* (3)内层循环时,持续比较当前数组的值与其后面(前面)数组值
* (4)当当前值大于后面值(小于前面值)时,交换
* 思想:外层每次循环都会将数组最小值放在“第一个”位置,同时后面的数组也可能会进行了一定的排序
* 时间复杂度:O(n²),性能优于简单的冒泡排序
*
* @param arrays 需要排序的数组
*/
public void normalBubbleSort(int[] arrays) {
int i, j;
for (i = 0; i < arrays.length; i++) {
for (j = arrays.length - 2; j >= i; j--) {
if (arrays[j] > arrays[j + 1]) {
Tools.swap(arrays, j, j + 1);
}
}
}
}
/**
* 优化冒泡排序
* (1)外层循环从第一个元素开始往后遍历
* (2)内层循环从后往前遍历至值与外层循环相等
* (3)内层循环时,持续比较当前数组的值与其后面(前面)数组值
* (4)当当前值大于后面值(小于前面值)时,交换
* (5)外层循环除了判断非数组越界外,还要判断内层整个一次遍历是否有进行排序
* (6)如果没有进行排序,则退出外层循环
* 思想:相比常规的冒泡排序,通过增加标志位的方式,可能会减少外层循环的次数,从而整体性能得到优化
* 时间复杂度:O(n²),性能优于常规的冒泡排序
*
* @param arrays 需要排序的数组
*/
public void betterBubbleSort(int[] arrays) {
int i, j;
boolean isSwap = true;
for (i = 0; i < arrays.length && isSwap; i++) {
isSwap = false;
for (j = arrays.length - 2; j >= i; j--) {
if (arrays[j] > arrays[j + 1]) {
Tools.swap(arrays, j, j + 1);
isSwap = true;
}
}
}
}
/**
* 简单选择排序
* (1)外层循环从第一个元素开始往后遍历
* (2)初始最小值数组下标等于当前外层循环的值
* (3)内层循环从外层的值开始往后遍历
* (4)如果“数组最小值”大于内层循环数组的值,则将最小值数组下标设置为内层循环的值
* (5)内层循环结束,判断最小值数组下标是否与外层循环的值相等,不等则将数组的两个值进行交换
* 思想:外层每循环一次,都会选择出最小数组值的下标,最后进行交换
* 时间复杂度:O(n²),性能优于冒泡排序
*
* @param arrays 需要排序的数组
*/
public void simpleSelectionSort(int[] arrays) {
int i, j, min;
for (i = 0; i < arrays.length; i++) {
min = i;
for (j = i + 1; j < arrays.length; j++) {
if (arrays[min] > arrays[j]) {
min = j;
}
}
if (i != min) {
Tools.swap(arrays, i, min);
}
}
}
/**
* 直接插入排序
* (1)外层循环从第二个元素开始往后遍历
* (2)判断外层循环当前数组的值是否小于其前面数组的值
* (3)如果不小于,则继续进行外层循环
* (4)如果小于,将该值设置为“哨兵”
* (5)内层循环从外层循环的前面一个数组值开始遍历
* (6)如果内层循环的值大于“哨兵”,则将内层循环当前数组值后移一位(复制到后面一位)
* (7)内层循环结束,将内层循环所进行到的数组下标后面的值设置为“哨兵”值
* 思想:外层每循环一次,都会将外层循环的值插入到已经排序好的前面的数组中
* 时间复杂度:O(n²),性能优于选择排序
*
* @param arrays 需要排序的数组
*/
public void insertSort(int[] arrays) {
int i, j, temp;
for (i = 1; i < arrays.length; i++) {
if (arrays[i] < arrays[i - 1]) {
temp = arrays[i];
for (j = i - 1; j >= 0 && arrays[j] > temp; j--) {
arrays[j + 1] = arrays[j];
}
arrays[j + 1] = temp;
}
}
}
/**
* 希尔排序
*
* @param arrays 需要排序的数组
*/
public void shellSort(int[] arrays) {
int i, j, temp;
int increment = arrays.length;
do {
increment = increment / 3 + 1;
for (i = increment; i < arrays.length; i++) {
if (arrays[i] < arrays[i - increment]) {
temp = arrays[i];
for (j = i - increment; j >= 0 && temp < arrays[j]; j -= increment) {
arrays[j + increment] = arrays[j];
}
arrays[j + increment] = temp;
}
}
} while (increment > 1);
}
/**
* 快速排序
* 时间复杂度:O(nlogn)
* 从空间与时间复杂的来说,目前最好的排序算法
*
* @param arrays
*/
public void quickSort(int[] arrays) {
qSort(arrays, 0, arrays.length - 1);
}
private void qSort(int[] arrays, int low, int high) {
int pivot;// 枢轴
if (low < high) {
pivot = partition(arrays, low, high);
qSort(arrays, low, pivot - 1);
qSort(arrays, pivot + 1, high);
}
}
private int partition(int[] arrays, int low, int high) {
int pivotKey;
getPivotKey(arrays, low, high);// 将相对中间值放在前面作为枢轴
pivotKey = arrays[low];// 用数字的第一个元素作为枢轴记录
int temp = pivotKey;
while (low < high) {
while (low < high && arrays[high] >= pivotKey) {
high--;
}
// Tools.swap(arrays, low, high);
arrays[low] = arrays[high];// 不使用交换
while (low < high && arrays[low] <= pivotKey) {
low++;
}
// Tools.swap(arrays, low, high);
arrays[high] = arrays[low];// 不使用交换
}
arrays[low] = temp;// 不使用交换
return low;// 返回枢轴所在的位置
}
private void getPivotKey(int[] arrays, int low, int high) {
int m = low + (high - low) / 2;
if (arrays[low] > arrays[high]) {// 将小的值放在前面
Tools.swap(arrays, low, high);
}
if (arrays[m] > arrays[high]) {// 将小的值放在中间
Tools.swap(arrays, m, high);
}
if (arrays[m] > arrays[low]) {
Tools.swap(arrays, low, m);// 将中间值放在前面
}
}
}
工具类:
public class Tools {
public static int[] initArray() {
int[] arrays = {23, 12, 54, 92, 85, 69, 43, 38, 42, 88};
return arrays;
}
public static void swap(int[] arrays, int i, int j) {
int temp = arrays[i];
arrays[i] = arrays[j];
arrays[j] = temp;
}
}
测试:
public class Test {
public static void main(String[] args) {
int[] ints = Tools.initArray();
for (int i = 0; i < ints.length; i++) {
System.out.printf("%2d ", ints[i]);
}
System.out.println();
SortType sortType = new SortType();
// sortType.SimpleBubbleSort(ints);
// sortType.normalBubbleSort(ints);
// sortType.betterBubbleSort(ints);
// sortType.simpleSelectionSort(ints);
// sortType.insertSort(ints);
// sortType.shellSort(ints);
sortType.quickSort(ints);
for (int i = 0; i < ints.length; i++) {
System.out.printf("%2d ", ints[i]);
}
}
}