四种排序算法

本文详细介绍了插入排序、选择排序、冒泡排序和快速排序四种排序算法的基本思想、时间复杂度和稳定性特点,并提供了每种算法的Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

四种排序算法

今天复习了插入,选择,冒泡,快速四种排序算法

首先列出各种算法的复杂度

排序方法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性
插入排序O(n²)O(n²)O(n)O(1)稳定
选择排序O(n²)O(n²)O(n²)O(1)不稳定
冒泡排序O(n²)O(n²)O(n)O(1)稳定
快速排序O(nlog₂n)O(n²)O(nlog₂n)O(nlog₂n)不稳定

稳定性:如果原本a在b前面而a=b排序后a是否仍在b前面

java的代码实现

1.插入排序

1.1基本思想
  1. 以第一个元素为基准默认第一个数字已经有序
  2. 取下一个元素,并且记录
  3. 从取到的元素位置向前找直到找到元素应该存在的位置
  4. 通过前移或者后移将该位置空出
  5. 将取出的元素存放的适合的位置
1.2代码实现
public static void sort(int arr[]){
    int i,j;
    //以第一个元素为基准默认第一个数字已经有序
    for ( i = 1; i < arr.length; i++) {
        //取下一个元素,并且记录
        int temp = arr[i];
        //从第i个位置开始向前找直到找到该元素应该存在的位置
        //该位置根据从小到大或者从大到小的不同判定也不同
        //在这里是从小到大
        for ( j = i; j > 0&& temp<arr[j-1]; j--) {
            //如果temp小于j-1个元素则将元素后移
            //j的位置就是temp应该在的位置依次向前找
            arr[j] = arr[j-1];
        }
        //将temp插入到正确的位置
        arr[j] = temp;
    }
    for (int k = 0; k < arr.length; k++) {
        System.out.println(arr[k]);
    }
}

2.选择排序

2.1基本思想
  1. 默认当前数是最小数记录下标
  2. 从当前数字开始向后找直到找到最小数的下标
  3. 若最小数位置不对则交换
  4. 该算法默认前面的数字总是有序
2.2代码实现
public static void sort(int arr[]){
    int temp=0;
    //一共比较n次
    for (int i = 0; i < arr.length; i++) {
        //认为目前的数就是最小的,记录最小数的下标
        int minIndex=i;
        //从i+1开始比较到最后一共
        for(int j=i+1;j<arr.length;j++){
            //比较大小总是记录最小数值的大小
            if(arr[minIndex]>arr[j]){
                minIndex = j;
            }
        }
        //最小数位置不对则交换前i个数字总是有序
        if (i != minIndex) {
            temp = arr[i];
            arr[i]=arr[minIndex];
            arr[minIndex] = temp;
        }
    }
}

3.冒泡排序

3.1基本思想

该算法要两两相邻比较将最小或者最大数逐渐前移或者后移形成有序序列

3.2代码实现
public static void sort(int[] a){
        int temp=0;
        //一共要排序n-1次
        for (int i = 0; i < a.length-1; ++i) {
            //每次要比较n-i-1次
            for (int j = 0; j < a.length-i-1; ++j) {
                //从小到大排序
//                if(a[j]>a[j+1]){
                //从大到小排序
                if(a[j]<a[j+1]){
                    temp = a[j];
                    a[j]=a[j+1];
                    a[j+1] = temp;
                }
            }
        }

4.快速排序

4.1基本思想

1.找出枢纽

2.分割成两部分

3.递归分别排左边和右边

  1. 挑选基准值:从数列中挑出一个元素,称为“基准”(pivot),
  2. 分割:重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(与基准值相等的数可以到任何一边)。在这个分割结束之后,对基准值的排序就已经完成,
  3. 递归排序子序列:递归地将小于基准值元素的子序列和大于基准值元素的子序列排序。

将数组分为两部分寻找枢纽

递归排序左数组和右数组

默认将最左边作为枢纽记录

交换比枢纽小的到枢纽左边

比枢纽大的到枢纽右边

全部扫描完成后更改枢纽位置

4.2代码实现
public static void quickSort(int[] arr){
    qsort(arr,0,arr.length-1);
}
private static void qsort(int[] arr,int low,int high){
    if(low<high){
        int pivot = partition(arr,low,high);//将数组分为两部分
        qsort(arr,low,pivot-1);//递归排序左数组
        qsort(arr,pivot+1,high);//递归排序右数组
    }
    for (int k = 0; k < arr.length; k++) {
        System.out.println(arr[k]);
    }
}
private static int partition(int[] arr,int low,int high){
    int pivot = arr[low];//把最左边作为枢轴记录
    while(low<high){
        while (low<high && arr[high]>=pivot) --high;
        arr[low] = arr[high];//交换比枢轴小的记录到左端
        while (low<high && arr[low]<pivot) ++ low;
        arr[high] = arr[low];//交换比枢轴小的记录到右端
    }
    //扫描完成,枢轴到位
    arr[low] = pivot;
    //返回枢轴位置
    return low;
}

更详细的注释版本:

package priv.wzb.sort.quicksort;

import priv.wzb.sort.Util;

/**
 * @author Satsuki
 * @time 2019/9/14 15:50
 * @description:
 * 1.找出枢纽
 * 2.分割成两部分
 * 3.递归分别排左边和右边
 */
public class QuickSort03 {

    public static void sort(int[] arr){
        qsort(arr,0,arr.length-1);

    }

    //递归排序
    public static void qsort(int[] arr,int low,int high){
        if (low<high){
            //找枢纽的位置
            int pivot = partition(arr,low,high);
            //递归排序左侧数组
            qsort(arr,low,pivot-1);
            //递归排序右侧数组
            qsort(arr,pivot+1,high);
        }

        Util.printf(arr);

    }

    //找出枢纽
    //分割数组
    public static int partition(int[] arr,int low,int high){
        //假设枢纽为数组开头第一个数字
        int pivot = arr[low];

        //循环条件当左边下标小于右边下标时循环分割数组
        //当条件不满足就是左边下标等于右边下标
        //也就是找到了pivot枢纽应该存放的位置
        //将枢纽归位即可
        while (low < high){
            //从最右边开始找
            //如果右侧数值大于pivot枢纽的数值则继续向前找即可
            while (low < high && arr[high]>=pivot){
                high--;
            }
            //当从右边开始找找到了一个小于枢纽并且存在于枢纽右边的数字时
            //将该数值扔到枢纽左边
            arr[low] = arr[high];

            //从右边找完就应该从左边再开始找
            //如果左边数值小于pivot则继续向后找
            while (low<high && arr[low]<pivot){
                low++;
            }
            //找到一个数值大于枢纽并且在枢纽左边
            //扔到枢纽右边
            arr[high] = arr[low];
        }

        //全部循环玩一遍之后当low=high时
        //就找到了枢纽应该存在的位置
        //就是给枢纽排序了
        //枢纽存在位置左边的数字永远小于枢纽
        //pivot存在位置右边的数字永远大于pivot
        //枢纽归位
        //此时的low==high
        arr[low] = pivot;

        //返回枢纽位置
        return low;

    }

    public static void main(String[] args) {
        int[] a = {0,10,9,2,4,6,4,3,1};
        sort(a);
    }
}
```**加粗样式**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值