排序算法记录(冒泡+快排+归并)

文章目录

    • 前言
    • 冒泡排序
    • 快速排序
    • 归并排序

前言

冒泡 + 快排 + 归并,这三种排序算法太过经典,但又很容易忘了。虽然一开始接触雀氏这些算法雀氏有些头大,但时间长了也还好。主要是回忆这些算法干了啥很耗时间。

如果在笔试时要写一个o(nlogn)的排序算法,如果不能立刻写出 快排或者归并,未免有些太浪费时间了。

故写这篇文章用于记录

tip: 一下内容均实现升序排序

冒泡排序

所谓冒泡,就是每一轮都排出一个最大的元素,把他丢在末尾。
在这里插入图片描述
如上图所示,5个元素的数组我们需要5轮遍历,每次遍历可以排出一个当前遍历区域内最大的元素

而确定最大元素的方法起始也很简单。每一次遍历,我们都和其前一个元素对比,也就是比较arr[j - 1]arr[j]。如果 arr[j - 1] > arr[j],则交换,否则不变。这样的比较方式让算法趋向于将大的元素向右边送,直到将最大的元素送到最右侧

当第一轮排序完成后,第二轮排序的范围则被缩小。因为已知最大元素在最右侧,那么无需遍历最右侧元素。

第三轮同理,无需遍历倒数第二个元素。以此类推

import java.util.*;public class Main {public static void main(String[] args) {// 冒泡int N;Scanner sc = new Scanner(System.in);N = sc.nextInt();int[] arr = new int[N];for (int i = 0; i < N; ++i) {arr[i] = sc.nextInt();}// sort 核心for (int i = 0; i < N; ++i) {for (int j = 1; j < N - i; ++j) {if (arr[j - 1] > arr[j]) {int tmp = arr[j];arr[j] = arr[j - 1];arr[j - 1] = tmp;}}}// printfor (int i = 0; i < N; ++i) {System.out.print(arr[i]);if (i < N - 1) System.out.print(" ");}}
}

快速排序

所谓快速排序,和俄罗斯套娃很像。我们想要快速排序俄罗斯套娃,可以做如下操作:

  1. 选出一个基准娃
  2. 遍历所有娃,小的放左边,大的放右边
  3. 如果两侧的娃不用排序,则终止
  4. 对基准娃左右两侧的娃娃们做1,2,3操作

快排也是类似的

在这里插入图片描述
不同的是,俄罗斯套娃是将别的元素摆放到基准娃的两侧;快排是通过交换左右两侧元素,定位到base的位置

import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int N = sc.nextInt();int[] arr = new int[N];for (int i = 0; i < N; ++i) {arr[i] = sc.nextInt();}// quickSortquickSort(arr, 0, N - 1);// printfor (int i = 0; i < N; ++i) {System.out.print(arr[i]);if (i < N - 1) System.out.print(" ");}}public static void quickSort(int[] arr, int lef, int rig) {if (lef >= rig) return;int base = arr[lef];int lp = lef, rp = rig;while (lp < rp) {// 右指针寻找到<base的数for (; rp > lp && arr[rp] >= base; --rp);arr[lp] = arr[rp];// 左指针寻找到>base的数for (; rp > lp && arr[lp] <= base; ++lp);arr[rp] = arr[lp];}arr[lp] = base;quickSort(arr, lef, lp - 1);quickSort(arr, lp + 1, rig);}
}

tip: 快排有一些注意点需要强调

  1. 递归终止条件,快排起始也是递归,是递归就需要终止条件。本题递归的终止条件就是lef >= rig,排序范围左侧端点不在右侧端点左边
  2. for (; rp > lp && arr[rp] >= base; --rp); 这个for相当于右侧小人,寻找 小于 base的数。因为是寻找小于,因此循环条件是 >= base就一直寻找
  3. 如果base是数组第一个元素,那么先走动的必须是右侧小人。因为数组最左侧元素,我们用base进行备份,先走右侧小人覆盖最左侧元素不会丢失base信息

归并排序

归并排序就有点蛋疼了,虽然代码极少(相对来说),但思维量如果不熟悉分治的情况下还是比较大的。

本文并非专业的介绍文章,感兴趣的读者可以详细阅读这篇文章

归并排序大致思路如下:

  1. 往死里拆分数组,具体拆分的方式就是对半拆
  2. 当拆分到不能再拆,局部合并

其中,mergeSort干的任务是对lef ~ right范围内的数组归并排序,merge属于归并排序中,的部分。

因为递归的原因,上层递归栈merge数组,以mid为临界区域,left ~ midmid + 1 ~ right这两段数组,内部元素都是局部递增的。这个原因很简单,因为递归的特性,回溯到上层栈,底层栈一定把功能实现好

这有点类似于甩锅,我排序全部数组太累了,于是找两个小弟,一个归并排序左边,一个排序右边。我不许用关心小弟怎么排序,我只需要知道,等小弟回来(回溯),我就只需要排序两个有序数组

所以要实现merge的功能,起始就是对两段有序数组进行排序

假设两段数组分别是arr1, arr2(实际上只有arr,为了方便叙述,我们说成两段)具体的排法是双指针遍历。

对于arr1, arr2。谁的元素大,谁就把元素按序存储到tmp中。

import java.util.*;public class Main {private static int[] tmp;public static void main(String[] args) {Scanner sc = new Scanner(System.in);int N = sc.nextInt();int[] arr = new int[N];tmp = new int[N];for (int i = 0; i < N; ++i) {arr[i] = sc.nextInt();}// mergemergeSort(arr, 0, N - 1);// printfor (int i = 0; i < N; ++i) {System.out.print(arr[i]);if (i < N - 1)System.out.print(" ");}sc.close();}public static void mergeSort(int[] arr, int left, int right) {if (left < right) {int mid = (left + right) / 2;mergeSort(arr, left, mid);mergeSort(arr, mid + 1, right);merge(arr, left, right);}}public static void merge(int[] arr, int left, int right) {int mid = (left + right) / 2;        int lp = left, rp = mid + 1, k = left;while (lp <= mid && rp <= right) {if (arr[lp] < arr[rp]) tmp[left++] = arr[lp++];else tmp[left++] = arr[rp++]; }while (lp <= mid) tmp[left++] = arr[lp++]; // 左区间没迭代完while (rp <= right) tmp[left++] = arr[rp++]; // 右区间没迭代完for (; k <= right; ++k) arr[k] = tmp[k]; // copy}
}

另外,值得一提的是,归并是上述三种排序中最快的。冒泡,快排都没有AC

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

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

相关文章

408学习笔记-17-C-C/C++中程序内存区域划分

C/C中程序内存区域划分 C/C程序内存分配的几个区域&#xff1a; 1、栈区(stack)&#xff1a;在执行函数时&#xff0c;函数内局部变量的存储单元都可以在栈上创建&#xff0c;函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中&#xff0c;效率很高…

基于python+vue拍卖行系统的设计与实现flask-django-nodejs-php

拍卖行系统的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品&#xff0c;体验高科技时代带给人们的方便&#xff0c;同时也能让用户体会到与以往常规产品不同的体验风格。 与安卓&#xff0c;iOS相比较起来&#xff0c;拍卖行…

Flink:维表 Join 难点和技术方案汇总

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

SQLiteC/C++接口详细介绍sqlite3_stmt类(十二)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍sqlite3_stmt类&#xff08;十一&#xff09; 下一篇&#xff1a; SQLiteC/C接口详细介绍sqlite3_stmt类&#xff08;十三&#xff09; 48、sqlite3_stmt_isexplain sqlite3_stmt_is…

2024蓝桥杯每日一题(单调队列)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一&#xff1a;单调栈 试题二&#xff1a;滑动窗口 试题三&#xff1a;子矩阵 试题四&#xff1a;最大子序和 试题一&#xff1a;单调栈 【题目描述】 给定一个长度为 N 的整数数列&#xff0c;输出每…

jvm提供的远程调试 简单使用

JVM自带远程调试功能 JVM远程调试&#xff0c;其实是两个虚拟机之间&#xff0c;通过socket通信&#xff0c;达到远程调试的目的&#xff1b; 前提 确保本地和远程的网络是开通的&#xff1b; 本地操作 远程操作 在启动命令参数中 把上面的内容复制进去

【3GPP】【核心网】【4G】4G手机接入过程,手机附着过程(超详细)

1. 4G手机接入过程&#xff0c;手机附着过程 附着&#xff08;Attach&#xff09;&#xff1a; 终端在PLMN中注册&#xff0c;从而建立自己的档案&#xff0c;即终端上下文 进行附着的三种情况&#xff1a; ①终端开机后的附着&#xff0c;初始附着 ②终端从覆盖盲区返回到…

解决用POI库生成的word文件中的表格在python-docx无法解析的问题

问题背景 用apache-poi生成word文件中表格&#xff0c;在使用python-docx库解析时报错&#xff1a; 问题分析 1. word文档本质上是一个rar压缩包&#xff0c;用winrar解析后如下&#xff1a; 2. 查看document.xml&#xff0c;可以看到table元素下面是没有<w:tblGrid>这…

Vue3快速上手(十七)Vue3之状态管理Pinia

一、简介 Pinia官网:https://pinia.vuejs.org/zh/ 从官网截图里可以直接看到,pinia是一个vuejs的状态(数据)管理工具。功能性同vuex。logo是小菠萝。它是一个集中式状态管理工具。就是将多个组件共用的数据管理起来,重复利用。有点类似缓存的意思。 二、Pinia环境搭建 …

【LVGL-按钮按钮矩阵部件】

LVGL-按钮&按钮矩阵部件 ■ LVGL-按钮部件■ 按钮部件&#xff1a; 点击三个按钮一个回调函数修改label值。 ■ LVGL-按钮矩阵部件■ 示例一&#xff1a;按钮换行&#xff0c;和宽度设置。■ 示例二&#xff1a;设置按钮宽度为2倍■ 示例三&#xff1a;获取点击的按钮下标&…

大数据主要组件HDFS Iceberg Hadoop spark介绍

HDFSIceberghadoopspark HDFS 面向PB级数据存储的分布式文件系统&#xff0c;可以存储任意类型与格式的数据文件&#xff0c;包括结构化的数据以及非结构化的数据。HDFS将导入的大数据文件切割成小数据块&#xff0c;均匀分布到服务器集群中的各个节点&#xff0c;并且每个数据…

Gartner发布网络安全应用生成式AI指南:应用生成增强功能提升企业网络安全能力和效率的三个领域及9个实例

生成增强功能是专门为提高知识工作者的生产力、解决网络安全技能短缺问题并降低大型语言模型带来的风险而构建的。安全和风险管理领导者通过在运营中采用生成增强来提高团队的能力。 主要发现 与其他人工智能实现相比&#xff0c;生成式人工智能 (GenAI)解决方案&#xff0c;特…

绿色节能|AIRIOT智慧建材能耗管理解决方案

建材供应是建筑业不可或缺的一个重要环节&#xff0c;在环保和企业可持续发展的双重需求下&#xff0c;建材生产商对建材生产过程中的能耗掌握和能耗管理尤其关注。但在实际生产和运营过程中&#xff0c;传统的建材能耗管理方式往往存在如下痛点&#xff1a; 用户管理权限不完善…

汽车ECU的虚拟化技术(五) -- 对MCU虚拟化实现难点的思考

目录 1.概述 2.虚拟化软件的难点 2.1 虚拟化中的中断处理 2.2 虚拟ECU的通信 3.小结 1.概述 在上面文章里汽车ECU的虚拟化技术(四) -- 对MCU虚拟化实现难点的思考-CSDN博客&#xff0c;解了OEM面临新的电子电气架构下的集成难点&#xff0c;引入了hypervisor以及VM调度机制…

ARM-Linux 开发板下安装编译 OpenCV 和 Dlib

安装 OpenCV 和 Dlib 不像在 x86 平台下那样简单&#xff0c;用一句命令就可以自动安装完。而在 ARM 平台中许多软件都需要自行下载编译&#xff0c;且还有许多问题&#xff0c;本篇文章就是记录在 ARM 平台下载 OpenCV 踩过的坑。 硬件环境&#xff1a; RK3568 Ubuntu20.04…

全国大学生数学建模大赛备赛——相关系数的求解(皮尔逊(pearson)、斯皮尔曼(spearman)、肯德尔(kendall)相关系数)

相关系数是用来衡量两个变量之间线性相关程度的指标。它的取值范围在-1到1之间&#xff0c;当相关系数为1时表示两个变量完全正相关&#xff08;即一个变大另一个也变大&#xff09;&#xff0c;当相关系数为-1时表示两个变量完全负相关&#xff08;即一个变大另一个变小&#…

定制 Elasticsearch 镜像

安装ik分词器 下载ik分词器 下载地址&#xff1a;https://github.com/infinilabs/analysis-ik/releases Dockerfile FROM docker.elastic.co/elasticsearch/elasticsearch:8.12.2 COPY ./elasticsearch-analysis-ik-8.12.2.zip /opt/ RUN bin/elasticsearch-plugin instal…

国产DSP FT-M6678开发-网络开发

简介 今天准备调试FT-M6678的网络部分,参考例程是《3. FT-M6678 Project\1. FT-M6678 接口驱动函数\13. GMAC\NDK 协议栈工程-V7.1\03应用例程\UDP\DSP端应用程序\DSP_UDP_Test_V7》,首先参照文档将NDK使用官方提供的NDK进行替换: 将D:\ti\pdk_C667…

FMEA助力新能源汽车行业腾飞:安全、效率双提升

随着新能源汽车市场的迅猛发展&#xff0c;各大车企纷纷加大研发力度&#xff0c;力求在激烈的市场竞争中脱颖而出。其中&#xff0c;FMEA&#xff08;故障模式与影响分析&#xff09;作为一种先进的质量管理工具&#xff0c;正被越来越多地应用于新能源汽车的研发和生产过程中…

深度学习pytorch——链式法则(Chain rule)(持续更新)

这篇文章将会以深度学习的角度解析链式法则。 基本的求导法则 高中的时候就学过&#xff0c;大学高数也巩固了一遍&#xff0c;这里不再赘述。 深度学习中的链式法则 为什么要讲述深度学习中的链式法则&#xff1f; 通过链式法则&#xff0c;我们可以得到中间层信息&#x…