排序算法(冒泡、插入、选择、快排、归并)原理动画及Python、Java实现

news2024/12/23 9:57:24

排序算法(冒泡、插入、选择、快排、归并)原理动画及Python、Java实现

  • 1 冒泡排序
    • 1.1 原理
    • 1.2 Python、Java实现
  • 2 插入排序
    • 2.1 原理
    • 2.2 Python、Java实现
  • 3 选择排序
    • 3.1 原理
    • 3.2 Python、Java实现
  • 4 快速排序
    • 4.1 原理
    • 4.2 Python、Java实现
  • 5 归并排序
    • 5.1 原理
    • 5.2 Python、Java实现

目前就总结这五种了,其它的后面看到了再弄。

1 冒泡排序

参考冒泡排序(详细图解分析+实现,小白一看就会)

1.1 原理

从序列的第一个元素开始,比较相邻两个元素,若顺序错误(如:从小到大排序时,前一个元素大于后一个元素),则交换位置。继续对下一对相邻元素执行相同的操作,直到序列的末尾。

核心:多趟排序,把最大的泡浮上来
每一轮排序的目的都是找到整个数组中最大的数并把它排在最后端,最后一个最大数不再比较移动。一轮一轮的比较,直到只剩下一个数时(完成了N趟的排序)这个排序就完成了,从而实现从小到大的排序。
在这里插入图片描述

1.2 Python、Java实现

def BubbleSort(nums):  # 从小到大
    n = len(nums)
    for i in range(n):  # 排序n轮
        for j in range(n - 1):  # 比较n-1组
            if nums[j] > nums[j + 1]:
                nums[j], nums[j + 1] = nums[j + 1], nums[j]
    return nums


nums = [29, 10, 14, 37, 12, 6, 32]
print(BubbleSort(nums))  # [6, 10, 12, 14, 29, 32, 37]

"""用一个标记优化"""
def BubbleSort(nums):  # 从小到大
    n = len(nums)
    for i in range(n):  # 排序n轮
        exchange = 0  # 标记是否进入排序循环
        for j in range(n - 1):  # 比较n-1组
            if nums[j] > nums[j + 1]:
                nums[j], nums[j + 1] = nums[j + 1], nums[j]
                exchange = 1
        # 如果前面的for循环都结束了,还没有一次交换,说明i后面已经完成了排序
        # 而前面的排序也已经在前面几轮中完成,所以可以直接跳出循环
        if exchange == 0:  
            break
    return nums


nums = [29, 10, 14, 37, 12, 6, 32]
print(BubbleSort(nums))  # [6, 10, 12, 14, 29, 32, 37]
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] nums = {29, 10, 14, 37, 12, 6, 32};
        BubbleSort(nums);
//        System.out.println(nums);  // 这样会直接输出地址
        System.out.println(Arrays.toString(nums));  // 一开始想的是循环输出,这样后面的"]"前面还会有", "出现
        // [6, 10, 12, 14, 29, 32, 37]
    }

    /*
    如果函数被声明为static,它就可以被类直接调用,而不需要实例化类对象。
    如果函数没有被声明为static,它就必须通过实例化类对象来调用。
     */
    public static void BubbleSort(int[] nums){
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n - 1; j++) {
                if (nums[j] > nums[j+1]) {
                    int temp = nums[j];
                    nums[j] = nums[j+1];
                    nums[j+1] = temp;
                }
            }
        }
    }

}

/*函数部分优化*/
    public static void BubbleSort(int[] nums){
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            int exchange = 0;
            for (int j = 0; j < n - 1; j++) {
                if (nums[j] > nums[j+1]) {
                    int temp = nums[j];
                    nums[j] = nums[j+1];
                    nums[j+1] = temp;
                    exchange = 1;
                }
            }
            if (exchange == 0){
                break;
            }
        }
    }

时间复杂度:O(n^2)

是稳定的吗?
稳定指的是相同的数的相对位置是否改变,即5, 0, 9, 11, 9里面的两个9最后位置是否变化。**冒泡排序是稳定的。**这一点在if nums[j] > nums[j + 1]中可以看出。

2 插入排序

十大排序算法(冒泡排序、插入排序、选择排序、希尔排序、堆排序、快排、归并排序、桶排序、计数排序、基数排序)

2.1 原理

就像是打扑克牌的摸牌过程,每从牌池里抽取一张牌,都会与手头已有的牌做比较,把它放在合适的位置。
在这里插入图片描述
描述:假设前n-1个元素已有序,现将第n个元素插入到前面已经排好的序列中,使得前n个元素有序,直到整个序列有序。一开始只能认为第一个元素是有序的,依次将其后面的元素插入到这个有序序列中来,直到整个序列有序为止。
在这里插入图片描述

2.2 Python、Java实现

def InsertSort(nums):  # 从小到大
    n = len(nums)
    for i in range(1, n):  # 外部插入排序,默认第一个数有序,从第二个数开始排序
        if nums[i] < nums[i-1]:  # 现在这个数小于前面的数时,才进入排序过程(就好像拿到了大王直接往后面一放,不需要进入手中的牌进行排序)
            temp = nums[i]  # 记录这个要插入的数
            p = i-1  # 从前面一个开始比较
            while nums[p] > temp and p >= 0:  # 指针指的数如果大于要插入的数,就往后挪一位
                nums[p+1] = nums[p]
                p -= 1
            nums[p+1] = temp  # 结束循环时,p指向小于temp的数
    return nums


nums = [29, 10, 14, 37, 12, 6, 32]
print(InsertSort(nums))  # [6, 10, 12, 14, 29, 32, 37]
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] nums = {29, 10, 14, 37, 12, 6, 32};
        InsertSort(nums);
//        System.out.println(nums);  // 这样会直接输出地址
        System.out.println(Arrays.toString(nums));  // 一开始想的是循环输出,这样后面的"]"前面还会有", "出现
        // [6, 10, 12, 14, 29, 32, 37]
    }

    public static void InsertSort(int[] nums){
        int n = nums.length;
        for (int i = 1; i < n; i++) {
            if (nums[i] < nums[i-1]){
                int temp = nums[i];
                int j;
                for (j = i-1; j >= 0 && nums[j] > temp; j--) {
                    /*
                    应该使用逻辑与符号 "&&" 而不是位与符号 "&"
                    因为逻辑与符号会在第一个条件不成立时直接跳出循环,而位与符号会继续执行第二个条件,可能导致数组越界异常
                     */
                    nums[j+1] = nums[j];
                }
                nums[j+1] = temp;
            }
        }
    }

}

时间复杂度:O(n^2),最好是O(n)

插入排序是稳定的。 这一点在while nums[p] > temp可以看出。

3 选择排序

选择排序(详细图解分析+实现,小白一看就会)

3.1 原理

核心:多趟选择
内层循环中:
第一次在所有n个数里面找最小值,与第一个数交换;
第二次在后面n-1个数里面找最小值,与n-1个数里面的第一个数交换……
在这里插入图片描述

3.2 Python、Java实现

def SelectSort(nums):  # 从小到大
    n = len(nums)
    for i in range(n):  # 排序n轮
        min_num = nums[i]
        min_index = i
        for j in range(i+1, n):
            if nums[j] < min_num:
                min_num = nums[j]
                min_index = j
        nums[i], nums[min_index] = nums[min_index], nums[i]

    return nums


nums = [29, 10, 14, 37, 12, 6, 32]
print(SelectSort(nums))  # [6, 10, 12, 14, 29, 32, 37]
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] nums = {29, 10, 14, 37, 12, 6, 32};
        SelectSort(nums);
        System.out.println(Arrays.toString(nums));  // [6, 10, 12, 14, 29, 32, 37]
    }


    public static void SelectSort(int[] nums){
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            int min_num = nums[i];
            int min_index = i;
            for (int j = i+1; j < n; j++) {
                if (nums[j] < min_num){
                    min_num = nums[j];
                    min_index = j;
                }
            }
            int temp = nums[i];
            nums[i] = nums[min_index];
            nums[min_index] = temp;
        }
    }

}

可以优化,设置成同时找最大值和最小值

时间复杂度:O(n^2)

选择排序是不稳定的。 因为发生了交换,如 3,3,2,2要和第一个3交换,则两个3就换了位置。

4 快速排序

【排序算法】快速排序(全坤式超详解)———有这一篇就够啦

4.1 原理

分治思想:随机选一个pivot(一般是最左边或者最右边),然后比 pivot 小的放左边、大的放右边。
在这里插入图片描述

4.2 Python、Java实现

用递归很快:

def QuickSort(nums):  # 从小到大
    if len(nums) <= 1:
        return nums
    else:
        pivot = nums[0]
        left = [num for num in nums[1:] if num < pivot]
        right = [num for num in nums[1:] if num >= pivot]

        return QuickSort(left) + [pivot] + QuickSort(right)


nums = [29, 10, 14, 37, 12, 6, 32]
print(QuickSort(nums))  # [6, 10, 12, 14, 29, 32, 37]

Java版本就不写了。
左右指针法之类的其实也用了递归,这里不写了。能搜到好多。

时间复杂度:O(nlogn),最坏情况是O(n^2)
不稳定。

5 归并排序

5.1 原理

同样是分治思想:
在这里插入图片描述

  1. 不断的分割数据,让数据的每一段都有序(一个数据相当于有序)
  2. 当所有子序列有序的时候,在把子序列归并,形成更大的子序列,最终整个数组有序。

核心:合并两个有序数组

在这里插入图片描述

5.2 Python、Java实现

def MergeSort(nums):  # 从小到大
    if len(nums) > 1:
        mid = len(nums) // 2  # 这里不能用 / 来除,会出现小数
        L = nums[:mid]
        R = nums[mid:]  # 递归到这里的时候,已经全部拆分成了长度为1的数组,也就是最底层

        # 递归
        MergeSort(L)
        MergeSort(R)

        # 到这一步的时候,其实就是开始从最底层处理,开始合并
        l = r = k = 0
        while l < len(L) and r < len(R):
            if L[l] <R[r]:
                nums[k] = L[l]
                l += 1
            else:
                nums[k] = R[r]
                r += 1
            k += 1

        # 左右数组长度可能不一样,所以还要检查是否还有剩余元素
        while l < len(L):  # 经过了上面,l按理来说应该正好等于len(L)了,如果还小于,说明有剩余的数
            nums[k] = L[l]
            l += 1
            k += 1
        while r < len(R):  # 经过了上面,l按理来说应该正好等于len(L)了,如果还小于,说明有剩余的数
            nums[k] = R[r]
            r += 1
            k += 1
            
    return nums


nums = [29, 10, 14, 37, 12, 6, 32]
print(MergeSort(nums))  # [6, 10, 12, 14, 29, 32, 37]

Java版本就不写了。
左右指针法之类的其实也用了递归,这里不写了。能搜到好多。

时间复杂度:O(nlogn)
稳定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2080816.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【机器学习】独立成分分析的基本概念、应用领域、具体实例(含python代码)以及ICA和PCA的联系和区别

引言 独立成分分析&#xff08;Independent Component Analysis&#xff0c;简称ICA&#xff09;是一种统计方法&#xff0c;用于从多个观察到的混合信号中提取出原始的独立信号源 文章目录 引言一、独立成分分析1.1 定义1.2 独立成分分析的基本原理1.3 独立成分分析的步骤1.3.…

RASA使用长文记录以及一些bug整理

RASA 学习笔记整理 一 安装 在虚拟环境中安装&#xff0c;进入python3版本的环境 conda activate python3 ai04机器旧版本&#xff1a;rasa-nlu和rasa-core是分开安装的 最新版本&#xff1a;rasa 将二者做了合并 直接安装 pip3 install rasa 在安装到如下步骤时候会报…

读软件开发安全之道:概念、设计与实施11安全地编程

1. 安全地编程 1.1. 在一个完整的软件设计过程中&#xff0c;我们要在创建和审查时就将安全性放在心中&#xff0c;但这只是产品开发过程的开始&#xff0c;接下来是实现、测试、部署、运行、监控、维护&#xff0c;并最终在生命周期结束时将其淘汰 1.2. 开发人员不仅必须忠实…

Android Launcher启动过程

## Launcher的启动流程&#xff1a; 1.Zygote进程 –> SystemServer进程 –> startOtherService方法 –> ActivityManagerService的systemReady方法 –> startHomeActivityLocked方法 –> ActivityStackSupervisor的startHomeActivity方法 –> 执行Activity…

Java | Leetcode Java题解之第380题O(1)时间插入、删除和获取随机元素

题目&#xff1a; 题解&#xff1a; class RandomizedSet {List<Integer> nums;Map<Integer, Integer> indices;Random random;public RandomizedSet() {nums new ArrayList<Integer>();indices new HashMap<Integer, Integer>();random new Rando…

Java9模块化系统JPMS(Java Platform Module System)

引言 随着Java技术的发展&#xff0c;开发人员面临的挑战之一是如何有效地管理和组织大型项目的依赖关系。传统的类路径&#xff08;classpath&#xff09;方法虽然简单&#xff0c;但在大型项目中却难以管理&#xff0c;尤其是在面对复杂的依赖关系时。为了解决这些问题&…

Kafka入门:从零开始了解分布式流处理平台

什么是Kafka Apache Kafka是由LinkedIn公司开发&#xff0c;后来由Apache软件基金会维护的一个分布式、分区、多副本的基于ZooKeeper协调的分布式消息系统。Kafka不仅是一个消息队列&#xff0c;还是一个强大的流处理平台&#xff0c;它能够实时地处理大量数据&#xff0c;满足…

Springboot如何实现redis消息的订阅发布

1. 环境准备 确保你已经安装了 Redis 服务器&#xff0c;并且可以在本地或者远程访问它。如果你还没有安装 Redis&#xff0c;请先安装并启动 Redis 服务。 2. 创建 Spring Boot 项目 使用 Spring Initializr 或者其他 IDE 创建一个新的 Spring Boot 项目&#xff0c;并添加以下…

Leetcode 1047-删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 题解 题目链接 //先进后出&a…

cubeide Target is not responding, retrying... 或基于vscode方式等 无法调试

点击调试输出如图&#xff1a; 基于cubeidet开发环境&#xff0c;debug后输出&#xff1a; 基于vscode开发环境&#xff1a; OpenOCD: GDB Server Quit Unexpectedly. See gdb-server output in TERMINAL tab for more details. 解决方法&#xff1a; 这里的调试选择一个&…

Vue3源码调试-第二篇

前言 上篇我们见到一个很厉害的方法&#xff0c;这篇我们来看看 baseCreateRenderer 首先&#xff0c;方法太多了&#xff0c;我也不一个一个数有多少个了&#xff0c;因为我们着重使用createApp方法&#xff0c;那么我们就跟着代码走&#xff0c;用到哪个方法就分析哪个方法…

vue的for循环不建议用index作为key

我们页面总有一些相似的&#xff0c;我们想用循环渲染&#xff0c;根据对象数组结构进行渲染&#xff0c;这是不是很熟悉的场景。这时候我们需要有一个唯一的key绑定在循环渲染的元素上&#xff0c;一般情况下我们会用id&#xff0c;因为id是唯一的。然而有些页面要循环的数据&…

python 把一个视频复制3次

1. 先看效果 输入 输出 2. 代码 第一种方法 moviepy 代码来源 gpt4o from moviepy.editor import VideoFileClip, clips_array# 加载视频 video VideoFileClip("a22.mp4")# 复制视频三次 video_copied clips_array([[video, video, video]])# 输出最终的视频 vi…

关于tresos Studio(EB)的MCAL配置之ADC

General Adc_DeInit API 使能Adc_DeInit接口 Adc Development Error Detection 开发者错误检测 Adc Enable Limit Check边界检测 Adc Queue启用队列&#xff0c;如果AdcPriorityImplementationADC_PRIORITY_HW_SW执行优先级为硬件则一定要开启队列 Adc_StartStopGroup API使…

XSS LABS - Level 14 过关思路

关注这个靶场的其他相关笔记&#xff1a;XSS - LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;关卡配置 这一关有些特殊&#xff0c;需要链接到外部站点&#xff0c;但是这个站点已经挂了&#xff0c;无法访问&#xff1a; 所以笔者就根据网上的资料&#xff0c;对这一关进…

ARM体系结构和接口技术(十一)定时器中断实验

文章目录 一、实验分析二、RCC章节&#xff1a;找到外设基地址并使能外设控制器时钟源1. RCC2. GICC和GICD3. TIM3 三、TIM3章节&#xff08;一&#xff09;CR1寄存器&#xff08;二&#xff09;DIER寄存器&#xff08;三&#xff09;SR寄存器&#xff08;四&#xff09;PSC寄存…

JS中this的指向问题、JS的执行机制、offset、client、scroll

JS中this的指向问题 1. 在全局环境下 在全局环境中&#xff08;在浏览器中是 window 对象&#xff0c;在Node.js中是 global 对象&#xff09;&#xff0c;this 指向全局对象。 console.log(this window); // 在浏览器中为 true console.log(this.document ! undefined); //…

基于ssm+vue+uniapp的农业电商服务系统小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

代码随想录算法训练营第四十一天 | 121. 买卖股票的最佳时机 , 122.买卖股票的最佳时机II , 123.买卖股票的最佳时机III

目录 121. 买卖股票的最佳时机 思路 暴力 贪心 动态规划 1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义 2.确定递推公式 3.dp数组如何初始化 4.确定遍历顺序 5.举例推导dp数组 方法一&#xff1a; 贪心 方法二&#xff1a;动态规划1 方法三&#xf…

使用rqt_console和roslaunch

1.使用rqt_console和rqt_logger_level rosrun rqt_console rqt_console 执行完该命令后有如下界面: 继续执行如下命令: rosrun rqt_logger_level rqt_logger_level 此时有如下新界面: 接下来继续运行如下命令: rosrun turtlesim turtlesim_node 上面第一…