插入排序
1.直接插入排序
- 时间复杂度:最好O(n) 、最坏O(n2) 、平均O(n2)
- 稳定
public class Main{
public static void main(String[] args) {
int[] nums={4,5,8,7,9,6,3,2,1};
int len=nums.length;
int num=-1;
for (int i = 1; i <len; i++) {
//先把当前元素给哨兵
num=nums[i];
int j;
for (j = i-1;j>=0&&num<nums[j]; j--) {
nums[j+1]=nums[j];
}
nums[j+1]=num;
}
System.out.println(nums);
}
}
2.希尔排序
交换排序
1. 冒泡排序
- 时间复杂度:最好O(n2)、最坏O(n2)、平均O(n2)
- 稳定
public class Main{
public static void main(String[] args) {
int[] nums={4,5,8,7,9,6,3,2,1};
int len=nums.length;
for (int i = 0; i < len - 1; i++) {
boolean flag=false; //表示本次遍历是否发生过交换
for (int j = len-1; j >i; j--) {
if(nums[j-1]>nums[j]){
int temp=nums[j];
nums[j]=nums[j-1];
nums[j-1]=temp;
flag=true;
}
}
if(!flag)break;
}
System.out.println(nums); //本趟遍历没有发生过交换,说明有序
}
}
2.快速排序
- 时间复杂度:最好O(n l o g 2 n {log_2{n}} log2n)、最坏O(n2)、平均O(n l o g 2 n {log_2{n}} log2n)
- 空间复杂度:O(n l o g 2 n {log_2{n}} log2n) 递归用到栈
- 不稳定
- Java代码
public class Main{
public static void main(String[] args) {
int[] nums = {4, 6, 8, 5, 9, 7, 2, 1, 3};
int low=0,high=nums.length-1;
QuickSort(nums,low,high);
System.out.println(nums);
}
//递归
private static void QuickSort(int[] nums, int low, int high) {
if(low>=high)return; //结束条件
if(low<high){
int pivotpos=Partition(nums,low,high);
QuickSort(nums,low,pivotpos-1);
QuickSort(nums,pivotpos+1,high);
}
}
//一次遍历确定一个元素位置
private static int Partition(int[] nums, int low, int high) {
int pivot=nums[low];
while (low<high){
while (low<high&&nums[high]>=pivot)--high;
nums[low]=nums[high];
while (low<high&&nums[low]<=pivot)++low;
nums[high]=nums[low];
}
nums[low]=pivot;
return low;
}
}
- 快排最坏的情况:
整个序列都已经有序或完全倒序,此时,快速排序退化为冒泡排序,要比较n2次才能完成。
选择排序
1.简单选择排序
- 时间复杂度:最好O(n2)、最坏O(n2)、平均O(n2)
- 空间复杂度:O(n)
- 不稳定
Java代码:
public class Main{
public static void main(String[] args) {
int[] nums = {5, 3, 6, 2, 4, 1};
int n=nums.length;
for (int i = 0; i < n - 1; i++) {
int min=i;
for (int j = i+1; j < n; j++) {
if(nums[j]<nums[min])min=j;
}
if(min!=i){
int temp=nums[min];
nums[min]=nums[i];
nums[i]=temp;
}
}
System.out.println(nums);
}
}
2.堆排序
- 时间复杂度:最好O(n l o g 2 n {log_2{n}} log2n)、最坏O(n l o g 2 n {log_2{n}} log2n)、平均O(n l o g 2 n {log_2{n}} log2n)
- 空间复杂度:O(1)
- 不稳定
归并排序
- 时间复杂度:最好O(n l o g 2 n {log_2{n}} log2n)、最坏O(n l o g 2 n {log_2{n}} log2n)、平均O(n l o g 2 n {log_2{n}} log2n)
- 空间复杂度:O(n)
- 稳定
- Java代码
public class Main{
public static void main(String[] args) {
int[] nums = {5, 3, 6, 2, 4, 1};
int low=0,high=nums.length-1;
Mergesort(nums,low,high);
System.out.println(nums);
}
private static void Mergesort(int[] nums, int low, int high) {
if(low<high){
int mid=(low+high)/2;
Mergesort(nums,low,mid);
Mergesort(nums,mid+1,high);
Merge(nums,low,mid,high);
}
}
private static void Merge(int[] nums, int low, int mid, int high) {
int[] b=new int[nums.length];
for (int i = low; i <=high; i++) {
b[i]=nums[i];
}
int i,j,k;
for(i=low,j=mid+1,k=i;i<=mid&&j<=high;++k){
if(b[i]<=b[j]){
nums[k]=b[i];
++i;
}else{
nums[k]=b[j];
++j;
}
}
while (i<=mid)nums[k++]=b[i++];
while (j<=high)nums[k++]=b[j++];
}
}
基数排序
- 时间复杂度:最好O(d(n+r))、最坏O(d(n+r))、平均O(d(n+r)),d趟分配和收集,一趟分配O(n),一趟收集O( r )
- 空间复杂度:O( r ) 代表的是队列的个数
- 稳定
- 如下,先以个位数进行第一轮
- 再以十位数进行第二轮
注意:不能从最高有效位进行比较排序,先排序最高位的话,在接下来的次高位排序会将最高位的顺序打乱,导致排序失败。