java数组之冒泡排序、快速排序

一、排序算法概述

1.算法定义

  • 排序:假设含有n个记录的序列为{R1,R2,...,Rn},其相应的关键字序列为{K1,K2,...,Kn}。将这些记录重新排序为{Ri1,Ri2,...,Rin},使得相应的关键字值满足条Ki1<=Ki2<=...<=Kin,这样的一种操作称为排序。

  • 通常来说,排序的目的是快速查找。

2.衡量排序算法的优劣

  • 时间复杂度:分析关键字的比较次数和记录的移动次数
  • 常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n<sup>2</sup>)<Ο(n<sup>3</sup>)<…<Ο(2<sup>n</sup>)<Ο(n!)<O(n<sup>n</sup>)
  • 空间复杂度:分析排序算法中需要多少辅助内存。

一个算法程序完全执行的时间容易受当前电脑的配置和当前运行的其他程序的影响,所以只使用程序执行时间来评价一个算法的优劣是不靠谱的。

一个算法的空间复杂度S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。

  • 稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。

 3.排序算法分类

  • 排序算法分类:内部排序和外部排序

    • 内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。

    • 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。

4.十大内部排序算法

数组的排序算法很多,实现方式各不相同,时间复杂度、空间复杂度、稳定性也各不相同:

常见时间复杂度所消耗的时间从小到大排序:

 O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)

5.十大排序算法(动画版)

 java数组之——了解十大排序算法(动画版)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_44554794/article/details/140423950

 二、冒泡排序

a) 排序思想

  1. 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。

  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

  3. 针对所有的元素重复以上的步骤,除了最后一个。

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止。

b)动态演示:

排序(冒泡排序,选择排序,插入排序,归并排序,快速排序,计数排序,基数排序) - VisuAlgo排序算法将一串数组(一个列表)中的元素(整数,数字,字符串等)按某种顺序(增大,减小,字典顺序等)重新排列。有很多种不同的排序算法,每一种都有各自的优势和限制。排序常常作为计算机课程中的介绍性问题,用以介绍一系列的算法思路。不失普遍性,我们在此可视化中,只将(可能包含重复)的整数数组排序至非减。试试点击 Bubble Sort 来可视化五个(含重复项)的杂乱整数的排序。icon-default.png?t=N7T8https://visualgo.net/zh/sorting

c)代码实现

代码实现一

public class Test19BubbleSort{
    public static void main(String[] args){
        int[] arr = {6,9,2,9,1};

        //目标:从小到大
        //冒泡排序的轮数 = 元素的总个数 - 1
        //轮数是多轮,每一轮比较的次数是多次,需要用到双重循环,即循环嵌套
        //外循环控制 轮数,内循环控制每一轮的比较次数和过程
        for(int i=1; i<arr.length; i++){ //循环次数是arr.length-1次/轮
            for(int j=0; j<arr.length-i; j++){
                //希望的是arr[j] < arr[j+1]
                if(arr[j] > arr[j+1]){
                    //交换arr[j]与arr[j+1]
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }

        //完成排序,遍历结果
        for(int i=0; i<arr.length; i++){
            System.out.print(arr[i]+"  ");
        }
    }
}

代码实现二(优化)

class Test19BubbleSort2{
    public static void main(String[] args) {
        int[] arr = {1, 3, 5, 7, 9};

        //从小到大排序
        for (int i = 0; i < arr.length - 1; i++) {
            boolean flag = true;//假设数组已经是有序的
            for (int j = 0; j < arr.length - 1 - i; j++) {
                //希望的是arr[j] < arr[j+1]
                if (arr[j] > arr[j + 1]) {
                    //交换arr[j]与arr[j+1]
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;

                    flag = false;//如果元素发生了交换,那么说明数组还没有排好序
                }
            }
            if (flag) {
                break;
            }
        }

        //完成排序,遍历结果
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "  ");
        }
    }
}

三、快速排序

1.快排简述

快速排序(Quick Sort)由图灵奖获得者Tony Hoare发明,被列为20世纪十大算法之一,是迄今为止所有内排序算法中速度最快的一种,快速排序的时间复杂度为O(nlog(n))。

快速排序通常明显比同为O(nlogn)的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多笔试面试中能经常看到快排的影子。

2.排序思想

a)从数列中挑出一个元素,称为"基准"(pivot),
b)重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
c)递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
d)递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

3.动态演示

https://visualgo.net/zh/sortingicon-default.png?t=N7T8https://visualgo.net/zh/sorting

 4.图示解说

a)第一轮

b)第二轮

 

5)内部排序的性能比较与选择

  • 性能比较

    • 从平均时间而言:快速排序最佳。但在最坏情况下时间性能不如堆排序和归并排序。

    • 从算法简单性看:由于直接选择排序、直接插入排序和冒泡排序的算法比较简单,将其认为是简单算法。对于Shell排序、堆排序、快速排序和归并排序算法,其算法比较复杂,认为是复杂排序。

    • 从稳定性看:直接插入排序、冒泡排序和归并排序时稳定的;而直接选择排序、快速排序、 Shell排序和堆排序是不稳定排序

    • 从待排序的记录数n的大小看,n较小时,宜采用简单排序;而n较大时宜采用改进排序。

  • 选择

    • 若n较小(如n≤50),可采用直接插入或直接选择排序。 当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插入,应选直接选择排序为宜。

    • 若文件初始状态基本有序(指正序),则应选用直接插入、冒泡或随机的快速排序为宜;

    • 若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。

5.代码实现

public class QuickSort {
    public static void main(String[] args) {
        int[] data = {9, -16, 30, 23, -30, -49, 25, 21, 30};
        System.out.println("排序之前:");
        for (int i = 0; i < data.length; i++) {
            System.out.print(data[i]+" ");
        }

        quickSort(data);//调用实现快排的方法

        System.out.println("\n排序之后:");
        for (int i = 0; i < data.length; i++) {
            System.out.print(data[i]+" ");
        }
    }

    public static void quickSort(int[] data) {
        subSort(data, 0, data.length - 1);
    }

    private static void subSort(int[] data, int start, int end) {
        if (start < end) {
            int base = data[start];
            int low = start;
            int high = end + 1;
            while (true) {
                while (low < end && data[++low] - base <= 0)
                    ;
                while (high > start && data[--high] - base >= 0)
                    ;
                if (low < high) {
                    //交换data数组[low]与[high]位置的元素
                    swap(data, low, high);
                } else {
                    break;
                }
            }
            //交换data数组[start]与[high]位置的元素
            swap(data, start, high);

            //经过代码[start, high)部分的元素 比[high, end]都小

            //通过递归调用,对data数组[start, high-1]部分的元素重复刚才的过程
            subSort(data, start, high - 1);
            //通过递归调用,对data数组[high+1,end]部分的元素重复刚才的过程
            subSort(data, high + 1, end);
        }
    }

    private static void swap(int[] data, int i, int j) {
        int temp = data[i];
        data[i] = data[j];
        data[j] = temp;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Keepalived实现双机热备(虚拟漂移IP地址)详细介绍

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️创作…

BI工具的AI革新:对话式分析如何引领企业智能转型?

在数据驱动的时代&#xff0c;数据分析早已成为企业决策制定的关键支撑。但是&#xff0c;很多企业在数字化转型的过程中&#xff0c;常常面临门槛高、流程复杂等问题。而AI技术的发展为解决上述问题带来了突破。 为了简化企业智能转型路径&#xff0c;帆软接入AI大模型技术&a…

Scherlokk - Mac 文件快速搜索对比工具

Scherlokk 是一款适用于 Mac 的文件内容快搜比较工具&#xff0c;在 Scherlokk 内输入关键词&#xff0c;即可在本地磁盘 / 移动硬盘 / 网络驱动器等区域内&#xff0c;查找包含该词的文件&#xff0c;快速定位所需文件&#xff0c;并提供文件比较、快速筛选过滤等功能。 两种…

SpringCloud--常用组件和服务中心

常用组件 Euroke和nacos 区别 负载均衡 负载均衡策略有哪些 自定义负载均衡策略

Power Apps使用oData访问表数据并赋值前端

在使用OData查询语法通过Xrm.WebApi.retrieveMultipleRecords方法过滤数据时&#xff0c;你可以指定一个OData $filter 参数来限制返回的记录集。 以下是一个使用Xrm.WebApi.retrieveMultipleRecords方法成功的例子&#xff0c;它使用了OData $filter 参数来查询实体的记录&am…

YOLOv5分类任务——手势识别

1. 下载YOLOv5官方代码 ONNX > CoreML > TFLite (github.com)">ultralytics/yolov5: YOLOv5 🚀 in PyTorch > ONNX > CoreML > TFLite (github.com) 2. 配置环境 打开终端,先建立名为YOLO5的环境,再将路径切换为requirements.txt文件夹所在的路径…

C#环境与数据类型

文章目录 C#环境.NET 框架集成开发环境 创建一个C#项目数据类型值类型引用类型对象类型object动态类型dynamic字符串类型string 指针类型 类型转换隐式转换显示转换&#xff08;强制转换&#xff09;C#提供的类型转换方法Convert类Parse方法TryParse方法 C#环境 .NET 框架 C#是…

Directory Opus 13 专业版(Windows 增强型文件管理器)值得购买?

在使用电脑时&#xff0c;总少不了和文件打交道。系统自带的 Explorer 资源管理器功能又非常有限&#xff0c;想要拥有一个多功能文件管理器吗&#xff1f; Directory Opus 是一款老牌多功能文件管理器&#xff0c;能很好地接管 Windows 资源管理器。 接管资源管理器 Directo…

Kotlin标准函数(语法糖)let with run also apply快速讲解

目录 1、知识储备——扩展函数 原理 定义扩展函数 调用扩展函数 2、返回值为上下文对象的标准函数 apply also 3、返回值为Lambda表达式结果 let run with 4、一表总结 1、知识储备——扩展函数 原理 Kotlin 在不继承父类或实现接口下&#xff0c;也能扩展一个类的…

硅谷甄选4(项目主体)

1.路由配置 1.1路由组件的雏形 src\views\home\index.vue&#xff08;以home组件为例&#xff09; 安装插件&#xff1a; 1.2路由配置 1.2.1路由index文件 src\router\index.ts //通过vue-router插件实现模板路由配置 import { createRouter, createWebHashHistory } fro…

【Qt 常用控件】

文章目录 1. Push Button 1. Push Button &#x1f427;给按钮设置图标

链接追踪系列-09.spring cloud项目整合elk显示业务日志

准备工作&#xff1a; 参看本系列之前篇&#xff1a;服务器安装elastic search 本机docker启动的kibana-tencent 使用本机安装的logstash。。。 本微服务实现的logstash配置如下&#xff1a; 使用腾讯云redis 启动本机mysql 启动本机docker 启动nacos,微服务依赖它作为…

防火墙的双机热备实验和通道策略

需求&#xff1a; 12&#xff0c;对现有网络进行改造升级&#xff0c;将当个防火墙组网改成双机热备的组网形式&#xff0c;做负载分担模式&#xff0c;游客区和DMZ区走FW3&#xff0c;生产区和办公区的流量走FW1 13&#xff0c;办公区上网用户限制流量不超过100M&#xff0c;…

象过河云进销存管理系统,简单、方便、高效!

在当今这个快节奏的商业时代&#xff0c;企业的日常运营管理愈发注重效率和便捷性。基于这样的需求&#xff0c;象过河云进销存管理系统应运而生&#xff0c;它以“简单、方便、高效”为核心价值&#xff0c;为众多企业量身打造了一站式的解决方案。 象过河云进销存管理系统打破…

MDK KEIL程序代码编译成静态库文件及库引用笔记教程

1、为什么要编译成库文件 在商业性的程序代码或软件中&#xff0c;各种静态库、动态库是非常常见的。甚至有许多的开源程序&#xff0c;其开放的源码工程中&#xff0c;也有一些程序代码是并不对外开放的&#xff0c;以一个静态库或动态库和一个头文件及部分说明文件的方式提供…

【Linux系列】TEE 命令:同时输出到终端和文件

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

AmazonS3部署以及nacos配置参数

AmazonS3部署 因为涉及到做的需求的头像的处理&#xff0c;所以需要去找头像的来源&#xff0c;没想到又是我们的老熟人&#xff0c;AmazonS3&#xff0c;巧了已经是第二次用了&#xff0c;上次我是用的别人的工具类去干的&#xff0c;这一次我这边自己编辑具体工具类型。 对应…

谷歌DeepMind被曝抄袭开源成果,论文还中了顶流会议

卡奥斯智能交互引擎是卡奥斯基于海尔近40年工业生产经验积累和卡奥斯7年工业互联网平台建设的最佳实践&#xff0c;基于大语言模型和RAG技术&#xff0c;集合海量工业领域生态资源方优质产品和知识服务&#xff0c;旨在通过智能搜索、连续交互&#xff0c;实时生成个性化的内容…

vue3+ECharts实现可视化中国地图

目录 版本问题解决 中国地图实现 版本问题解决 目前echarts的最新版本为5.5.1 echarts在4.9.0版本以后移除了中国地图&#xff0c;所以如果的你的版本高于4.9.0就需要手动导入中国地图。版本低于或者等于4.9.0则不需要导入。 这里我分享一种导入方法&#xff1a; 1.将项目的…

SQL中的谓词与谓词下推

在 SQL 查询中&#xff0c;谓词&#xff08;Predicate&#xff09;是用来对数据进行过滤的条件。它们决定了数据从数据库表中被选择的条件。理解和正确使用 SQL 谓词对于编写高效查询至关重要。 目录 什么是谓词&#xff1f;一个真实的故事SQL 谓词的代码示例比较谓词逻辑谓词…