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

news2024/9/20 16:13:19

文章目录

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

前言

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

如果在笔试时要写一个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;
                }
            }
        }

        // print
        for (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();
        }

        // quickSort
        quickSort(arr, 0, N - 1);

        // print
        for (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();
        }

        // merge
        mergeSort(arr, 0, N - 1);

        // print
        for (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.coloradmin.cn/o/1537332.html

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

相关文章

java学习——集合

目录 一、集合框架介绍 1、集合与集合框架说明 2、使用集合框架原因 3、集合框架接口体系 二、Collection接口 1、Collection常用方法 2、AbstractCollection 三、迭代器 1、迭代器说明 2、自定义Collection集合 四、泛型 1、泛型说明 2、使用泛型方法 3、泛型通配…

哲♂学家带你深♂入了♂解结构体及结构体内存大小问题

目录 概要 一、结构体的声明 二、结构体变量的创建和初始化 三、结构体的特殊声明 四、结构体内存对齐 1、对齐原则 2、例一 对齐数 计算方法 3、例二 总结 概要 结构体是我们日常编程中经常要用到的一种自定义类型&#xff0c;使用起来也是十分的方便。接下来就由…

ts js vue 验证文件 MD5 值 spark-md5

ts js vue 验证文件 MD5 值 spark-md5 如何在前端中验证要上传的文件的 md5 值 一、安装 spark-md5 插件 需要用到 spark-md5 这个插件 官方 github&#xff1a;https://github.com/satazor/js-spark-md5/tree/master yarn add spark-md5 // 或 npm i spark-md5使用的时候引…

TCP | TCP协议格式 | 三次握手

1.TCP协议 为什么需要 TCP 协议 &#xff1f;TCP 工作在哪一层&#xff1f; IP网络层是不可靠的&#xff0c;TCP工作在传输层&#xff0c;保证数据传输的可靠性。 TCP全称为 “传输控制协议&#xff08;Transmission Control Protocol”&#xff09;。 TCP 是面向连接的、可靠…

KDB+Q | D1 | 学习资源 基础数据类型

官网会是主要的学习资源&#xff1a;https://code.kx.com/q/ 中文教程可能读起来会快一点&#xff1a; https://kdbcn.gitee.io/ 参考了还不错的学习经验帖&#xff1a;https://www.jianshu.com/p/488764d42627 KDB擅长处理时序数据&#xff0c; KDB数据库是后端数据库&…

MySQL数据库存储引擎MyISAM与InnoDB

前言 MySQL存储引擎是MySQL数据库中负责管理数据存储和检索的组件&#xff0c;不同的存储引擎提供了不同的功能和特性&#xff0c;可以根据实际需求选择合适的存储引擎来优化数据库性能和功能。以下是一些常见的MySQL存储引擎&#xff1a;InnoDB、MyISAM、MEMORY、NDB Cluster…

Ribbon知识点

1、通过类实现重写Ribbon规则 1.1注意 这个类一定不能跟启动类放在同一个包下面&#xff0c;不能被componentScan给扫描到。 需要如图放置&#xff1a; 要是被componentScan给扫描到&#xff0c;则会被所有的服务提供方所共享&#xff0c;那么就不能实现指定服务用不同的Ribbo…

权限提升-Windows权限提升篇溢出漏洞宝塔面板BypassCS插件化MSF模块化

知识点 1、Web到Win系统提权-权限差异原因 2、Web到Win系统提权-溢出漏洞&#xff08;MSF&CS&#xff09; 3、Web到Win系统提权-集成软件&#xff08;哥斯拉模块Bypass&#xff09; 章节点&#xff1a; 1、Web权限提升及转移 2、系统权限提升及转移 3、宿主权限提升及转移…

【Java Web基础】一些网页设计基础(四)

文章目录 1. 做Tab切换2. 下面的内容展示——Card样式3. 采供分类&#xff0c;分类用面包屑导航做4. 出名企业展示&#xff0c;就是普通的图片5. 用热门商品类似的panel做一个农博会展览 1. 做Tab切换 使用BootStrap提供的样式&#xff1a; <ul class"nav nav-tabs&q…

【Linux】系统开启和关闭过程

Linux 系统启动过程 BIOS 自检&#xff1a;在计算机开机时&#xff0c;BIOS 会进行自检&#xff0c;检查硬件设备是否正常。 加载引导程序&#xff1a;BIOS 自检完成后&#xff0c;会加载引导程序&#xff0c;如 GRUB、LILO 等。引导程序会加载内核和初始化 RAM 磁盘&#xff…

005——串口移植(基于鸿蒙liteos-a)

目录 一、 Liteos-a中串口的使用 1.1 内核里打印 1.2 APP控制台 ​编辑 1.2.1 /dev/console 1.2.2 /dev/serial 1.2.3 /dev/uartddev-0 1. 总体介绍 2. device_t 3. drvier_t 4. uartdev_fops 1.2.4 uart_ops 二、 鸿蒙串口内部的一些机制&#xff08;流水账&…

实用福利网站分享

1.http://www.w3school.com.cn w3school&#xff0c;很好的在线web学习网站&#xff0c;免费 2.https://sklearn.apachecn.org sklearn文档&#xff0c;虽然是文档&#xff0c;但能学到很多很多具体的机器学习例子和知识 3.http://www.runoob.com 菜鸟教程&#xff0c;也是…

GTC大会干货:8位大佬对Transformer起源和未来发展的探讨

在2024年的GTC大会上&#xff0c;黄仁勋特邀Transformer机器语言模型的七位创造者&#xff0c;共同探讨Transformer模型的过去、现在与未来。他们一致认为&#xff0c;尽管Transformer已经成为现代自然语言处理领域的基石&#xff0c;但这个世界仍然需要超越Transformer的新颖架…

使用远程工具连接Mysql

&#xff08;若想要远程连接Mysql需要下面解决四个问题&#xff09; 1、目标地址 直接查询 2、端口号 3306 3、防火墙关闭 [rootlocalhost date]# systemctl stop firewalld.service 4、授权mysql数据库root用户权限&#xff08;因为mysql开始不允许其他IP访问&#xff0…

Java 栈与队列

一、栈 在Java中&#xff0c;实现栈有两个方法&#xff1a; Java本身的集合类型Stack类型。Stack集合类型继承于Vector&#xff0c;由于Vector是通过数组实现的&#xff0c;所以Stack集合类型也是通过数组来实现的。借用LinkedList来间接实现栈。LinkedList是双向链表&#x…

【pcolor数据可视化】Matlab vs. Python

1、Matlab代码及结果 代码 clear;clc load(.\nclcolormap.mat)sl [0,50,100,200,500,0]; el [50,100,200,500,1000,200];for i 1:length(sl)file [..\data\static_result\VIS_Min-,num2str(sl(i)),to,num2str(el(i)),_yearly.npy];data readNPY(file);maskreadNPY(.\mas…

2024阿里云服务器99计划优惠活动_开年采购季优惠价格表

2024阿里云开年采购活动3月优惠&#xff0c;99计划云服务器99元一年、免费领取上云扶持优惠券&#xff0c;不只是云服务器、云数据库、存储、云电脑、域名等均有活动&#xff0c;阿里云服务器网aliyunfuwuqi.com整理阿里云开年采购上云无忧活动入口、优惠价格表和优惠券领取详细…

【Linux】信号的处理{信号处理的时机/了解寄存器/内核态与用户态/信号操作函数}

文章目录 0.对于信号捕捉的理解1.信号处理的时机1.1 何时处理信号&#xff1f;1.2 内核态和用户态1.3 内核态和用户态的切换 2.了解寄存器3.信号捕捉的原理4.信号操作函数4.1sighandler_t signal(int signum, sighandler_t handler);4.2int sigaction(int signum, const struct…

代码随想录算法训练营第三十一天 | 455. 分发饼干、376. 摆动序列、53. 最大子数组和

代码随想录算法训练营第三十一天 | 455. 分发饼干、376. 摆动序列、53. 最大子数组和 455. 分发饼干题目解法 376. 摆动序列题目解法 53. 最大子数组和题目解法 感悟 455. 分发饼干 题目 解法 class Solution { public:int findContentChildren(vector<int>& g, vec…

大模型时代,5个最顶级的向量数据库

介绍5个向量数据库。 大模型时代&#xff0c;向量数据库彻底的火了&#xff0c;今天我分享业内最频繁使用的向量数据库&#xff0c;更多实践经验&#xff0c;可以文末参加我们的技术落地的讨论&#xff0c;喜欢本文记得收藏、关注、点赞。 1 Chroma 使用ChromaDB构建LLM应用程…