文章目录
插入排序
直接插入排序
直接插入排序:将待排序的元素插入到前面已经排序好的序列中
折半插入排序
当 low>high 时折半查找停⽌,应将 [low, i-1] 内的元素全部右移,并将 A[0] 复制到 low 所指位置
希尔排序(内部使用:直接插入)
交换排序
冒泡排序
从后往前(或从前往后)两两⽐较相邻元素的值,若为逆序(即A[i-1]>A[i]),则交换它们,直到序列⽐较完。称这样过程为“⼀趟”冒泡排序。
快速排序
package sort;
import java.util.Arrays;
public class Test6
{
public static void main(String[] args)
{
int[]arr= {-9,78,30,0,23,-567,70};
quickSort(arr, 0, arr.length-1);
System.out.println("arr="+Arrays.toString(arr));
}
public static void quickSort(int[] arr, int left, int right)
{
int l = left; //左下标
int r = right; //右下标
//pivot 中轴值
int pivot = arr[(left + right) / 2];
int temp = 0; //临时变量,作为交换时使用
//while循环的目的是让比pivot 值小放到左边
//比pivot 值大放到右边
while (l < r)
{
//在pivot的左边一直找,找到大于等于pivot值,才退出
while (arr[l] < pivot)
{
l += 1;
}
//在pivot的右边一直找,找到小于等于pivot值,才退出
while (arr[r] > pivot)
{
r -= 1;
}
//如果l >= r说明pivot 的左右两的值,已经按照左边全部是
//小于等于pivot值,右边全部是大于等于pivot值
if (l >= r)
{
break;
}
//交换
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
//如果交换完后,发现这个arr[l] == pivot值 相等 r--, 前移
if (arr[l] == pivot)
{
r -= 1;
}
//如果交换完后,发现这个arr[r] == pivot值 相等 l++, 后移
if (arr[r] == pivot)
{
l += 1;
}
}
// 如果 l == r, 必须l++, r--, 否则为出现栈溢出
if (l == r)
{
l += 1;
r -= 1;
}
//向左递归
if (left < r)
{
quickSort(arr, left, r);
}
//向右递归
if (right > l)
{
quickSort(arr, l, right);
}
}
}
package sort;
import java.util.Arrays;
public class Test6_1
{
public static void main(String[] args)
{
//给出无序数组
int arr[] =
{
72, 6, 57, 88, 60, 42, 83, 73, 48, 85
};
//输出无序数组
System.out.println(Arrays.toString(arr));
//快速排序
quickSort(arr);
//partition(arr,0,arr.length-1);
//输出有序数组
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int[] arr)
{
int low = 0;
int high = arr.length - 1;
quickSort(arr, low, high);
}
private static int partition(int[] arr, int low, int high)
{
//指定左指针i和右指针j
int i = low;
int j = high;
//将第一个数作为基准值。挖坑
int x = arr[low];
//使用循环实现分区操作
while (i < j)
{//5 8
//1.从右向左移动j,找到第一个小于基准值的值 arr[j]
while (arr[j] >= x && i < j)
{
j--;
}
//2.将右侧找到小于基准数的值加入到左边的(坑)位置, 左指针想中间移动一个位置i++
if (i < j)
{
arr[i] = arr[j];
i++;
}
//3.从左向右移动i,找到第一个大于等于基准值的值 arr[i]
while (arr[i] < x && i < j)
{
i++;
}
//4.将左侧找到的打印等于基准值的值加入到右边的坑中,右指针向中间移动一个位置 j--
if (i < j)
{
arr[j] = arr[i];
j--;
}
}
//使用基准值填坑,这就是基准值的最终位置
arr[i] = x;//arr[j] = y;
//返回基准值的位置索引
return i; //return j;
}
private static void quickSort(int[] arr, int low, int high)
{//???递归何时结束
if (low < high)
{
//分区操作,将一个数组分成两个分区,返回分区界限索引
int index = partition(arr, low, high);
//对左分区进行快排
quickSort(arr, low, index - 1);
//对右分区进行快排
quickSort(arr, index + 1, high);
}
}
}
- 最好情况:每趟快速排序选择的枢轴元素划分很均匀——排序趟数O(log 2 n)
- 每趟可确定多个元素的最终位置
选择排序
简单选择排序
每⼀趟在待排序元素中选取关键字最⼩的元素加⼊有序⼦序列
加入的方法是:这个最小元素与第一个待排序元素交换位置
n个元素的简单选择排序需要 n-1 趟处理
堆排序
堆排序的插入与删除
二路归并排序(外部排序)
最好最坏的比较次数
问:将有序数组 归并排序 最多与最少比较次数
设有两个有序数组 arr1 与 arr2,数组长度分别为 m 与 n, 要合并成一个长度位 m+n 的有序数组 arr3.
最差情况下:比较次数为 m+n-1
此时,将数组 arr1 与数组 arr2 中的元素两两比较,将值小的放进数组 arr3, 直到数组 arr3 填满为止。
因为 arr3 有 m+n 个空位,每次两两比较就放进去一个数,而最后一个剩下的元素可以不用比较直接放进去,所以一共两两比较了 m+n-1 次。
最好情况下:比较次数为 min{m, n}
一定要注意,这是简单归并排序,必须从第一个元素比。
因此,最好情况下,至少需要两两比较一个数组的长度,比较次数为 min{m,n}
基数排序
算法复杂度总结