选择排序
把数组分为有序和无序的两部分,每次从无序的部分中找到最小的元素与无序部分的第一个元素进行交换,无序部分减1,有序部分加1。
运行时间与输入无关,数据移动是最少的。
public void selectSort(int[] nums) {
for (int i = 0; i < nums.length; i++) {
int min = i; // 最小数的索引
// 从后面找到最小的数
for (int j = i + 1; j < nums.length; j++) {
if (nums[min] > nums[j]) {
min = j;
}
}
// 将无序部分最小的数放到无序部分的最前面
int temp = nums[i];
nums[i] = nums[min];
nums[min] = temp;
}
}
冒泡排序
冒泡排序通过不断地比较两个相邻元素,将较大的元素交换到右边,从而实现排序。
public void bubbleSort(int[] nums) {
boolean flag = true;
for (int i = 0; i < nums.length && flag; i++) {
flag = false;
for (int j = 0; j < nums.length - i - 1; j++) {
if (nums[j] > nums[j+1]) {
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
flag = true;
}
}
}
}
对冒泡排序进行优化
优化的原因:比如说排序 4 2 1 6 7 8
即使 6 7 8 已经有序了,但执行内循环的时候还是会将 4 6 7 8 继续向后比较,虽然不会交换
因此可以记录最后一次交换的位置,减少不必要的比较。
public void bubbleSort(int[] nums) {
boolean flag = true;
int lastSwapIndex = 0; // 记录最后一次交换的位置,为无序的最后的一个元素的位置
int sortBorder = nums.length - 1; // 有序部分与无序部分的边界
for (int i = 0; i < nums.length && flag; i++) {
flag = false;
// 所以内循环只要执行到无序部分的边界就行了
for (int j = 0; j < sortBorder; j++) {
if (nums[j] > nums[j+1]) {
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
flag = true;
lastSwapIndex = j;
}
}
sortBorder = lastSwapIndex;
}
}
插入排序
将无序部分的每个元素依次插入到有序部分中。
运行时间取决于输入数组的顺序,对一个接近有序的数据进行排序会很快。
优化:可以对有序部分进行二分查找,找到无序部分的第一个数应该放到的位置,再将有序的部分元素向右移动,这样可以减少比较的次数。
public void insertSort(int[] nums) {
// i从1开始是因为我们将第一个元素当作有序处理
for (int i = 1; i < nums.length; i++) {
int temp = nums[i];
int j = i - 1;
// 将当前第i个数插入到前面有序序列中
// 将较大的数向右移动,不需要交换元素的插入排序
for (; j >= 0 && temp < nums[j]; j--) {
nums[j + 1] = nums[j];
}
nums[j + 1] = temp;
}
}
插入排序的递归实现
// 对序号为 n 的元素进行插入排序
public void insertSortRecursive(int[] nums, int n) {
if (n == 0) {
return;
}
insertSortRecursive(nums, n - 1);
int temp = nums[n];
int j = n - 1;
for (; j >= 0 && nums[j] > temp; j--) {
nums[j + 1] = nums[j];
}
nums[j + 1] = temp;
}
希尔排序
public void shellSort(int[] nums) {
for (int index = fib.length - 1; index >= 0; index--) {
int step = fib[index];
for (int i = 0; i < nums.length; i += step) {
int temp = nums[i];
int j = i - step;
// 将当前第i个数插入到前面有序序列中
// 将较大的数向右移动,不需要交换元素的插入排序
for (; j >= 0 && temp < nums[j]; j -= step) {
nums[j + step] = nums[j];
}
nums[j + step] = temp;
}
}
}
两个测试的方法
// 判断数组是否有序
public static boolean isSorted(int[] nums) {
for (int i = 0; i < nums.length - 1; i++) {
if (nums[i + 1] < nums[i]) {
return false;
}
}
return true;
}
// 打印数组
public static void printArray(int[] nums) {
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
System.out.println();
}