算法与数据结构全阶班-左程云版(二)基础阶段之3.归并排序和快速排序(下)

简介: 本文主要介绍了两种排序,归并排序和快速排序,归并排序有递归和非递归2种方式实现,快速排序的升级版为荷兰国旗问题。

2.快速排序

Partition过程:

给定一个数组arr,和一个整数num。请把小于等于num的数放在数组的左边,大于num的数放在数组的右边;

要求额外空间复杂度O(1),时间复杂度O(N)。

思路如下:

2345_image_file_copy_125.jpg

Partition过程升级版(荷兰国旗问题):

给定一个数组arr,和一个整数num。请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边;

要求额外空间复杂度O(1),时间复杂度O(N)。

思路如下:

2345_image_file_copy_126.jpg

两种分区实现如下:

public class PartitionAndQuickSort {
    /*
    普通分区:
    给定一个数组arr和一个整数num,
    请把小于等于num的数放在数组的左边,
    大于num的数放在数组的右边
     */
    public static int partition(int[] arr, int L, int R) {
        if (L > R) {
            return -1;
        }
        if (L == R) {
            return L;
        }
        int lessEqual = L - 1;
        int index = L;
        while (index < R) {
            if (arr[index] <= arr[R]) {
                swap(arr, index, ++lessEqual);
            }
            index++;
        }
        swap(arr, ++lessEqual, R);
        return lessEqual;
    }
    /*
    分区升级版:荷兰国旗:
    给定一个数组arr和一个整数num
    请把小于num的数放在数组的左边,
    等于num的数放在数组的中间,
    大于num的数放在数组的右边
     */
    public static int[] netherlandsFlag(int[] arr, int L, int R) {
        if (L > R) {
            return new int[]{-1, -1};
        }
        if (L == R) {
            return new int[]{L, R};
        }
        int less = L - 1, more = R;
        int index = L;
        while (index < more) {
            if (arr[index] == arr[R]) {
                index++;
            } else if (arr[index] < arr[R]) {
                swap(arr, index++, ++less);
            } else {
                swap(arr, index, --more);
            }
        }
        swap(arr, more, R);
        return new int[]{less + 1, more};
    }
    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

快速排序:

快速排序有3种方式:

(1)利用普通分区算法;

(2)利用荷兰国旗算法;

(3)随机选数与最后一个数交换,再利用荷兰国旗算法。

分析时间复杂度:

随机快排的时间复杂度分析:

1)通过分析知道,划分值越靠近中间,性能越好;越靠近两边,性能越差

2)随机选一个数进行划分的目的就是让好情况和差情况都变成概率事件

3)把每一种情况都列出来,会有每种情况下的时间复杂度,但概率都是1/N

4)那么所有情况都考虑,时间复杂度就是这种概率模型下的长期期望,

时间复杂度O(N*logN),额外空间复杂度O(logN)都是这么来的。

(1)前两种:

最差情况是数组已经有序:

2345_image_file_copy_128.jpg

(2)第三种

一般情况是获取到的随机数在数组中间位置附近,就属于较好的情况:

2345_image_file_copy_129.jpg

2345_image_file_copy_130.jpg

空间复杂度:

2345_image_file_copy_131.jpg

最差情况下是O(N),累加求期望收敛于O(LogN)。

3种快速排序实现如下:

public static void quickSort1(int[] arr) {
    if (null == arr || arr.length < 2) {
        return;
    }
    process1(arr, 0, arr.length-1);
}
public static void process1(int[] arr, int L, int R) {
    if (L >= R) {
        return;
    }
    int M = partition(arr, L, R);
    process1(arr, L, M - 1);
    process1(arr, M + 1, R);
}
public static void quickSort2(int[] arr) {
    if (null == arr || arr.length < 2) {
        return;
    }
    process2(arr, 0, arr.length-1);
}
public static void process2(int[] arr, int L, int R) {
    if (L >= R) {
        return;
    }
    int[] equalArea = netherlandsFlag(arr, L, R);
    process1(arr, L, equalArea[0] - 1);
    process1(arr, equalArea[1]+ 1, R);
}
public static void quickSort3(int[] arr) {
    if (null == arr || arr.length < 2) {
        return;
    }
    process3(arr, 0, arr.length-1);
}
public static void process3(int[] arr, int L, int R) {
    if (L >= R) {
        return;
    }
    swap(arr, (int) (Math.random() * (R + 1)), R);
    int[] equalArea = netherlandsFlag(arr, L, R);
    process1(arr, L, equalArea[0] - 1);
    process1(arr, equalArea[1]+ 1, R);
}

总结

归并排序有很多个应用场景,一般应用在数组中左边的数比右边的数满足某个条件时,进行某个操作,都可以在归并的过程中进行解决。

相关文章
|
27天前
|
搜索推荐 C语言
【排序算法】快速排序升级版--三路快排详解 + 实现(c语言)
本文介绍了快速排序的升级版——三路快排。传统快速排序在处理大量相同元素时效率较低,而三路快排通过将数组分为三部分(小于、等于、大于基准值)来优化这一问题。文章详细讲解了三路快排的实现步骤,并提供了完整的代码示例。
52 4
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
90 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
2月前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
40 4
|
2月前
|
机器学习/深度学习 搜索推荐 算法
探索数据结构:初入算法之经典排序算法
探索数据结构:初入算法之经典排序算法
|
2月前
|
算法 Java 索引
数据结构与算法学习十五:常用查找算法介绍,线性排序、二分查找(折半查找)算法、差值查找算法、斐波那契(黄金分割法)查找算法
四种常用的查找算法:顺序查找、二分查找(折半查找)、插值查找和斐波那契查找,并提供了Java语言的实现代码和测试结果。
27 0
|
2月前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
8天前
|
算法
基于GA遗传算法的PID控制器参数优化matlab建模与仿真
本项目基于遗传算法(GA)优化PID控制器参数,通过空间状态方程构建控制对象,自定义GA的选择、交叉、变异过程,以提高PID控制性能。与使用通用GA工具箱相比,此方法更灵活、针对性强。MATLAB2022A环境下测试,展示了GA优化前后PID控制效果的显著差异。核心代码实现了遗传算法的迭代优化过程,最终通过适应度函数评估并选择了最优PID参数,显著提升了系统响应速度和稳定性。
|
5天前
|
算法
基于WOA鲸鱼优化的购售电收益与风险评估算法matlab仿真
本研究提出了一种基于鲸鱼优化算法(WOA)的购售电收益与风险评估算法。通过将售电公司购售电收益风险计算公式作为WOA的目标函数,经过迭代优化计算出最优购电策略。实验结果表明,在迭代次数超过10次后,风险价值收益优化值达到1715.1万元的最大值。WOA还确定了中长期市场、现货市场及可再生能源等不同市场的最优购电量,验证了算法的有效性。核心程序使用MATLAB2022a实现,通过多次迭代优化,实现了售电公司收益最大化和风险最小化的目标。
|
3天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于深度学习网络的宝石类型识别算法matlab仿真
本项目利用GoogLeNet深度学习网络进行宝石类型识别,实验包括收集多类宝石图像数据集并按7:1:2比例划分。使用Matlab2022a实现算法,提供含中文注释的完整代码及操作视频。GoogLeNet通过其独特的Inception模块,结合数据增强、学习率调整和正则化等优化手段,有效提升了宝石识别的准确性和效率。
|
9天前
|
算法
基于大爆炸优化算法的PID控制器参数寻优matlab仿真
本研究基于大爆炸优化算法对PID控制器参数进行寻优,并通过Matlab仿真对比优化前后PID控制效果。使用MATLAB2022a实现核心程序,展示了算法迭代过程及最优PID参数的求解。大爆炸优化算法通过模拟宇宙大爆炸和大收缩过程,在搜索空间中迭代寻找全局最优解,特别适用于PID参数优化,提升控制系统性能。