算法-03-排序-归并-快速排序

冒泡排序、插入排序、选择排序这三种排序算法,它们的时间复杂度都是O(n^2),比较高,适合小规模数据的排序。如果数据量大,我们就需要使用到时间复杂度低的排序算法,归并排序快速排序是复杂度为O(nlogn)的排序算法。

1-归并排序(Merge Sort)

如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。具体的流程如下:

从图中,我们看到归并排序实际是用到了分治的思想。将一个大问题分解成小的子问题来解决。小的子问题解决了,大问题也就解决了。

java 复制代码
@Slf4j
public class MergeSort {
    public static void main(String[] args) {
        int []arr = {23,18,37,16,45,40,3,28,19};
        sort(arr);
        log.info("排序后的数组:arr={}",arr);

    }
    public static void sort(int []arr){
        int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
        sort(arr,0,arr.length-1,temp);
    }

    private static void sort(int[] arr,int left,int right,int []temp){
        if(left<right){
            int mid = (left+right)/2;
            sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
            sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
            merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
        }
    }
    private static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;//左序列指针
        int j = mid+1;//右序列指针
        int t = 0;//临时数组指针
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[t++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[t++] = arr[j++];
        }
        t = 0;
        //将temp中的元素全部拷贝到原数组中
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
}

(1)归并排序是一个稳定的排序算法;

(2)最好情况、最坏情况,还是平均情况,时间复杂度都是O(nlogn);

(3)空间复杂度是O(n)。

2-快速排序

快速排序算法(Quicksort),我们习惯性把它简称为"快排"。快排利用的也是分治思想。快排的思想是这样的:如果要排序数组中下标从p到r之间的一组数据,我们选择p到r之间的任意一个数据作为pivot(分区点)。

下面的流程就是快排的一个轮回:

快速排序的代码实现:

java 复制代码
@Slf4j
public class QuickSort2 {
    public static void main(String[] args) {
        //初始化需要排序的数组
        int array[] = {9, 2, 11, 7, 12, 5};
        //快速排序
        quickSort(array, 0, array.length - 1);
        //打印出排序好的序列
        log.info("排序好的数组,array={}", array);
    }

    //快速排序
    private static void quickSort(int[] array, int low, int high) {
        if (low < high) {
            //找到分区的位置,左边右边分别进行快速排序
            int index = partition(array, low, high);
            quickSort(array, 0, index - 1);
            quickSort(array, index + 1, high);
        }
    }

    //快速排序分区操作
    private static int partition(int[] array, int low, int high) {
        //选择基准
        int pivot = array[low];       
        //当左指针小于右指针时,重复操作
        while (low < high) {
            while (low < high && array[high] >= pivot) {
                high = high - 1;
            }
            array[low] = array[high];
            while (low < high && array[low] <= pivot) {
                low = low + 1;
            }
            array[high] = array[low];
        }
        //最后赋值基准
        array[low] = pivot;       
        //返回基准所在位置,基准位置已经排序好
        return low;
    }
}

快排是一种原地、不稳定的排序算法。快排的平均时间复杂度是O(nlogn),最好的时间复杂度O(nlogn),最差的时间复杂度是O(n^2)。

相关推荐
王中阳Go1 小时前
从超市收银到航空调度:贪心算法如何破解生活中的最优决策谜题?
java·后端·算法
故事挺秃然2 小时前
中文分词:机械分词算法详解与实践总结
算法·nlp
车队老哥记录生活4 小时前
【MPC】模型预测控制笔记 (3):无约束输出反馈MPC
笔记·算法
地平线开发者5 小时前
BEV 感知算法评价指标简介
算法·自动驾驶
不过四级不改名6775 小时前
用c语言实现简易c语言扫雷游戏
c语言·算法·游戏
C++ 老炮儿的技术栈7 小时前
手动实现strcpy
c语言·开发语言·c++·算法·visual studio
倔强的石头_7 小时前
【数据结构与算法】利用堆结构高效解决TopK问题
后端·算法
倔强的石头_7 小时前
【数据结构与算法】详解二叉树下:实践篇————通过链式结构深入理解并实现二叉树
后端·算法
哎写bug的程序员8 小时前
leetcode复盘(1)
算法·leetcode·职场和发展
风靡晚8 小时前
用于汽车毫米波雷达的四维高分辨率点云图像
人工智能·算法·机器学习·计算机视觉·汽车·信息与通信·信号处理