排序算法(归并排序、快速排序)

给你n个乱序的整数,让你将它们按照从小到大的顺序排列,这个问题看起来很简单,今天我来介绍几种非常著名的排序算法

归并排序

归并排序是经典的分治思想,要一下子完成n个数的排序不容易,可以把它从中间分割开,分别对左半部分和由半部分的数字排序,然后将两个有序的数组合并起来就得到最终的有序数组

同理,如果左右部分还是很长怎么办?继续分,直到只有一个数的时候,这个局部数组是有序的直接返回

伪代码

归并排序思想的伪代码如下:

复制代码
递归函数:

如果当前只有一个元素,返回

递归排序左半部分

递归排序右半部分

合并两边的数组

假设有一组样例 7,2,4,5,1,8

依照归并排序的思想可以将数组作以下划分

当数组递归到只有一个元素返回后,它的上一层递归就可以将两个有序数组合并,然后继续返回到上一次,以此合并两个有序数组并返回的过程如下图:

代码

java 复制代码
//归并排序
public class MergerSort {
    int[] b;
    public MergerSort(int[] b) {
        //初始化中间数组
        this.b = b;
    }
    public void sort(int[] a,int left,int right) {
        //只有一个元素不用排序
        if(left==right) {
            return;
        }
        //大于1个元素
        int mid=(left+right)/2;
        //分治策略,将数组分成两半分别排序
        sort(a,left,mid);
        sort(a,mid+1,right);

        //左右两部分都排序完毕,将它们合并
        //左半部分数组的下标
        int l_index=left;
        //右半部分数组的下标
        int r_index=mid+1;
        //中间数组b的下标
        int index=left;
        //将两个有序数组合并到一起,直到一个数组为空
        while(l_index<=mid&&r_index<=right) {
            if(a[l_index]<a[r_index]) {
                b[index]=a[l_index];
                l_index++;
            }else{
                b[index]=a[r_index];
                r_index++;
            }
            index++;
        }
        //剩下的数组是有序的直接插入到数组b的后面即可
        while(l_index<=mid){
            b[index++]=a[l_index++];
        }
        while(r_index<=right){
            b[index++]=a[r_index++];
        }

        //将有序的数组复制到原数组中
        for(int i=left;i<=right;i++){
            a[i]=b[i];
        }
    }
}

快速排序

快速排序和归并排序很像,也是利用分治的思想,快速排序每次从数组中选一个数当作中间值,把小于这个中间值的数组放到数组的左边,把大于这个数的值放到数组的右边,然后递归调用自己分别对左半部分和右半部分执行如上操作

中间值的选取

只是说了要选一个中间值,那么到底该选数组中的哪个数作为中间值呢?

常用的就是选择数组中的第一个数当作中间值,不过在极端情况下时间复杂度会退化到n方。

也可以随机选取数组中的一个数当作中间值

还有一种,就是比较左右两端和中间的数字,选介于中间的那个数当作中间值

这里我就用第一种,选择数组中的第一个数当作中间值

伪代码

java 复制代码
快速排序:

如果当前只有一个元素,返回

设置两个指针变量(i,j)分别指向数组头和尾
选择第一个数当作中间值 pivot
while(i<j){
    从后往前找到第一个小于pivot的
    从前往后找到第一个大于pivot的
    如果i<j,交换这两个数
}

将下标j对应的数和数组第一个数交换

递归对左半部分数组做同样操作
递归对右半部分数组做同样操作

代码

java 复制代码
public class QuickSort {

    public void sort(int[] a,int low,int high) {

        if(low>=high) {
            return;
        }
        int partition = partition(a, low, high);

        sort(a,low,partition-1);
        sort(a,partition+1,high);
    }

    //选第一个元素当标准,并划分左右两部分数组
    public int partition(int[] a,int low,int high) {

        int pivot = a[low];
        int i = low;
        int j = high;
        while(i<j) {
            while(i<j&&a[j]>=pivot) j--;
            while(i<j&&a[i]<=pivot) i++;
            //交换
            if(i<j){
                int temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
        }
        //将数组中第一个元素即中间值和下标j对应的元素交换
        a[low] = a[j];
        a[j] = pivot;
        return j;
    }
}
相关推荐
roman_日积跬步-终至千里38 分钟前
【机器学习】“回归“算法模型的三个评估指标:MAE(衡量预测准确性)、MSE(放大大误差)、R²(说明模型解释能力)
算法·机器学习·回归
kokunka41 分钟前
【数据结构】栈的顺序存储(整型栈、字符栈)
数据结构
小指纹2 小时前
图论-最短路Dijkstra算法
数据结构·c++·算法·深度优先·图论
赴3353 小时前
逻辑回归 银行贷款资格判断案列优化 交叉验证,调整阈值,下采样与过采样方法
算法·机器学习·逻辑回归·下采样·交叉验证·过采样·阈值
2501_924878733 小时前
无人机光伏巡检缺陷检出率↑32%:陌讯多模态融合算法实战解析
开发语言·人工智能·算法·视觉检测·无人机
沉睡的无敌雄狮3 小时前
无人机光伏巡检漏检率↓78%!陌讯多模态融合算法实战解析
人工智能·算法·计算机视觉·目标跟踪
magicwt4 小时前
《从零构建大模型》读书笔记
算法
大胖猫L4 小时前
深搜与广搜在 TypeScript 类型递归中的应用
前端·算法
2202_756749695 小时前
02 基于sklearn的机械学习-KNN算法、模型选择与调优(交叉验证、朴素贝叶斯算法、拉普拉斯平滑)、决策树(信息增益、基尼指数)、随机森林
python·算法·决策树·随机森林·机器学习·sklearn
ATaylorSu5 小时前
经典算法之美:冒泡排序的优雅实现
开发语言·笔记·学习·算法