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

给你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;
    }
}
相关推荐
Two_brushes.1 小时前
【算法】宽度优先遍历BFS
算法·leetcode·哈希算法·宽度优先
森焱森3 小时前
水下航行器外形分类详解
c语言·单片机·算法·架构·无人机
QuantumStack5 小时前
【C++ 真题】P1104 生日
开发语言·c++·算法
写个博客5 小时前
暑假算法日记第一天
算法
绿皮的猪猪侠5 小时前
算法笔记上机训练实战指南刷题
笔记·算法·pta·上机·浙大
hie988946 小时前
MATLAB锂离子电池伪二维(P2D)模型实现
人工智能·算法·matlab
杰克尼6 小时前
BM5 合并k个已排序的链表
数据结构·算法·链表
.30-06Springfield7 小时前
决策树(Decision tree)算法详解(ID3、C4.5、CART)
人工智能·python·算法·决策树·机器学习
我不是哆啦A梦7 小时前
破解风电运维“百模大战”困局,机械版ChatGPT诞生?
运维·人工智能·python·算法·chatgpt
xiaolang_8616_wjl7 小时前
c++文字游戏_闯关打怪
开发语言·数据结构·c++·算法·c++20