排序算法基本原理及实现2

                                                                                             

                                   📑打牌 : da pai ge的个人主页
                                   🌤️个人专栏 : da pai ge的博客专栏
                                  ☁️宝剑锋从磨砺出,梅花香自苦寒来

🌤️冒泡排序

🌤️原理

在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序

private void swap(int[] array, int i, int j) {

   int t = array[i];

   array[i] = array[j];

   array[j] = t;

}

private void createHeap(int[] array) {

   for (int i = (array.length - 1) / 2; i >= 0; i--) {

       shiftDown(array, array.length, i);

  }

}

public static void shiftDown(int[] array, int size, int index) {

   int left = 2 * index + 1;

   while (left < size) {

       int max = left;

  int right = 2 * index + 2;

       if (right < size) {

           if (array[right] > array[left]) {

               max = right;

          }

      }

       

       if (array[index] >= array[max]) {

           break;

      }

       

       int t = array[index];

       array[index] = array[max];

       array[max] = t;

       

       index = max;

       left = 2 * index + 1;

  }

}

时间复杂度

空间复杂度

最好O(n)

平均O(n^2)

最坏O(n^2)

数据有序数据逆序

🌤️实现

public static void bubbleSort(int[] array) {

for (int i = 0; i < array.length - 1; i++) {

boolean isSorted = true;

for (int j = 0; j < array.length - i - 1; j++) {

// 相等不交换,保证稳定性

if (array[j] > array[j + 1]) {

swap(array, j, j + 1);

isSorted = false;

}

}

if (isSorted) {

break;

}

}

}

🌤️快速排序

🌤️原理-总览

1. 从待排序区间选择一个数,作为基准值(pivot);

2. Partition: 遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基准值大的(可

以包含相等的)放到基准值的右边;

3. 采用分治思想,对左右两个小区间按照同样的方式处理,直到小区间的长度 == 1,代表已经有序,或者小区间

的长度 == 0,代表没有数据。

实现:

public static void quickSort(int[] array) {

quickSortInternal(array, 0, array.length - 1);

}

// [left, right] 为待排序区间

private static void quickSortInternal(int[] array, int left, int right) {

if (left == right) {

return;

}

if (left > right) {

return;

}

// 最简单的选择基准值的方式,选择 array[left] 作为基准值

// pivotIndex 代表基准值最终停留的下标

int pivotIndex = partition(array, left, right);

// [left, pivotIndex - 1] 都是小于等于基准值的

// [pivotIndex + 1, right] 都是大于等于基准值的

quickSortInternal(array, left, pivotIndex - 1);

quickSortInternal(array, pivotIndex + 1, right);

}

🌤️原理-partition

Hoare :

实现:

private static int partition(int[] array, int left, int right) {

int i = left;

int j = right;

int pivot = array[left];

while (i < j) {

while (i < j && array[j] >= pivot) {

j--;

}



while (i < j && array[i] <= pivot) {

i++;

}



swap(array, i, j);

}

swap(array, i, left);

return i;

}

挖坑

基本思路和Hoare 法一致,只是不再进行交换,而是进行赋值(填坑+挖坑)

实现:

前后遍历法:

private static int partition(int[] array, int left, int right) {

int d = left + 1;

int pivot = array[left];

for (int i = left + 1; i <= right; i++) {

if (array[i] < pivot) {

swap(array, i, d);

d++;

}

}

swap(array, d, left);



return d;

}

🌤️性能分析

时间复杂度

空间复杂度

最好 平均O(n * log(n))

最坏 最好O(n * log(n))

平均 最坏O(n^2) O(log(n)) O(log(n)) O(n)

稳定性:不稳定

🌤️原理-基准值的选择

1. 选择边上(左或者右)

2. 随机选择

3. 几数取中(例如三数取中):array[left], array[mid], array[right] 大小是中间的为基准值

🌤️原理-非递归分治

public static void quickSort(int[] array) {

Stack<Integer> stack = new Stack<>();

stack.push(array.length - 1);

stack.push(0);



while (!stack.isEmpty()) {

int left = stack.pop();

int right = stack.pop();

if (left >= right) {

continue;

}



int pivotIndex = partition(array, left, right);

stack.push(right);

stack.push(pivotIndex + 1);



stack.push(pivotIndex - 1);

stack.push(left);

}

}

🌤️优化总结

1. 选择基准值很重要,通常使用几数取中法

2. partition 过程中把和基准值相等的数也选择出来

3. 待排序区间小于一个阈值时(例如 48),使用直接插入排序

🌤️总结

1. 在待排序区间选择一个基准值

1. 选择左边或者右边

2. 随机选取

3. 几数取中法

2. 做 partition,使得小的数在左,大的数在右

1. hoare

2. 挖坑

3. 前后遍历

4. 将基准值相等的也选择出来(了解)

3. 分治处理左右两个小区间,直到小区间数目小于一个阈值,使用插入排序

🌤️归并排序

🌤️原理-总览

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and

Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子

序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

🌤️原理-合并两个有序数组

private static void merge(int[] array, int low, int mid, int high) {

int i = low;

int j = mid;

int length = high - low;

int[] extra = new int[length];

int k = 0;



// 选择小的放入 extra

while (i < mid && j < high) {

// 加入等于,保证稳定性

if (array[i] <= array[j]) {

extra[k++] = array[i++];

} else {

extra[k++] = array[j++];

}

}



// 将属于元素放入 extra

while (i < mid) {

extra[k++] = array[i++];

}



while (j < right) {

extra[k++] = array[j++];

}

时间复杂度

空间复杂度

O(n * log(n))

O(n)

数据不敏感

数据不敏感

// 从 extra 搬移回 array

for (int t = 0; t < length; t++) {

// 需要搬移回原位置,从 low 开始

array[low + t] = extra[t];

}

}

🌤️实现

public static void mergeSort(int[] array) {

mergeSortInternal(array, 0, array.length);

}

// 待排序区间为 [low, high)

private static void mergeSortInternal(int[] array, int low, int high) {

if (low - 1 >= high) {

return;

}



int mid = (low + high) / 2;

mergeSortInternal(array, low, mid);

mergeSortInternal(array, mid, high);



merge(array, low, mid, high);

}

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

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

相关文章

解决mybatis-plus中,当属性为空的时候,update方法、updateById方法无法set null,直接忽略了

问题描述 当indexId set 22的时候是可以set的 我们发现sql语句也是正常的 表中数据也被更改了 但是当我们indexId为空的时候 sql语句中没有了set indexId这一属性。。 既然属性都没了&#xff0c;表是肯定没做修改的 问题解决 在实体类对应的字段上加注解TableField(strategy…

每日一练【有效三角形的个数】

一、题目描述 611. 有效三角形的个数 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 示例 1: 输入: nums [2,2,3,4] 输出: 3 解释:有效的组合是: 2,3,4 (使用第一个 2) 2,3,4 (使用第二个 2) 2,2,3示例 2: 输入: nums [4,2…

《WebGIS快速开发教程》第5版“惊喜”更新啦

我的书籍《WebGIS快速开发教程》第5版&#xff0c;经过忙碌的编写&#xff0c;终于发布啦&#xff01; 先给大家看看新书的封面&#xff1a; 这次的封面我们经过了全新的设计&#xff0c;不同于以往的任何一个版本。从封面就可以看出第5版肯定有不小的更新。 那么我们话不多说…

ChatGPT,作为一种强大的自然语言处理模型,具备显著优势,能够帮助您在各个领域取得突破

2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车…

Linux服务器部署XXL-JOB

参考文档及下载地址&#xff1a;分布式任务调度平台XXL-JOB 1 从git拉取XXL-JOB代码 我们的大部分变动&#xff0c;是发生在xxl-job-admin&#xff0c;最终将这个模块打包成jar包部署在linux服务器上。 2 执行数据库脚本 doc\db\tables_xxl_job.sql 3 修改pom文件&#xff0c…

【Linux】信号的保存和捕捉

文章目录 一、信号的保存——信号的三个表——block表&#xff0c;pending表&#xff0c;handler表sigset_t信号集操作函数——用户层sigprocmask和sigpending——内核层 二、信号的捕捉重谈进程地址空间&#xff08;第三次&#xff09;用户态和内核态sigaction可重入函数volat…

语义分割 LR-ASPP网络学习笔记 (附代码)

论文地址&#xff1a;https://arxiv.org/abs/1905.02244 代码地址&#xff1a;https://github.com/WZMIAOMIAO/deep-learning-for-image-processing/tree/master/pytorch_segmentation/lraspp 1.是什么&#xff1f; LR-ASPP是一个轻量级语义分割网络&#xff0c;它是在Mobil…

如何做好软文推广的选题?媒介盒子分享常见套路

选题是软文推广的重中之重&#xff0c;主题选得好&#xff0c;不仅能够戳到用户&#xff0c;提高转化率&#xff0c;还能让各位运营的写作效率大幅度提升&#xff0c;今天媒介盒子就来和大家分享软文选题的常见套路&#xff0c;助力各位品牌进行选题。 一、 根据产品选题 软文…

安卓开发APP应用程序和苹果iOS开发APP应用程序有什么区别?

随着智能手机和平板电脑在全球的普及&#xff0c;APP移动应用已成为日常生活中不可或缺的组成部分。从社交网络到电子商务平台&#xff0c;从个人理财到游戏娱乐&#xff0c;APP几乎渗透了人们所有的活动领域。在开发APP时&#xff0c;开发者通常要面对两大主流平台&#xff1a…

鸿蒙4.0开发笔记之ArkTS语法基础的UI描述、基础组件的使用与如何查看组件是否有参数(八)

文章目录 一、声明式UI描述1、无/有参数组件2、如何查看组件是否有参数 二、Image组件的使用三、组件的属性设置四、补充1、使用组件的成员函数配置组件的事件方法2、配置子组件3、多组件嵌套 一、声明式UI描述 在HarmonyOS的ArkTS语法中&#xff0c;万物皆组件。ArkTS以声明方…

Spring-Boot---配置文件

文章目录 配置文件的作用配置文件的格式PropertiesProperties基本语法读取Properties配置文件 ymlyml基本语法读取yml配置文件 Properties VS Yml 配置文件的作用 整个项目中所有重要的数据都是在配置文件中配置的&#xff0c;具有非常重要的作用。比如&#xff1a; 数据库的…

【TiDB理论知识09】TiFlash

一 TiFlash架构 二 TiFlash 核心特性 TiFlash 主要有 异步复制、一致性、智能选择、计算加速 等几个核心特性。 1 异步复制 TiFlash 中的副本以特殊角色 (Raft Learner) 进行异步的数据复制&#xff0c;这表示当 TiFlash 节点宕机或者网络高延迟等状况发生时&#xff0c;Ti…

SCAU:18049 迭代法求平方根

18049 迭代法求平方根 时间限制:1000MS 代码长度限制:10KB 提交次数:0 通过次数:0 题型: 填空题 语言: G;GCC;VC Description 使用迭代法求a的平方根。求平方根的迭代公式如下&#xff0c;要求计算到相邻两次求出的x的差的绝对值小于1E-5时停止&#xff0c;结果显示4位小…

神经网络模型流程与卷积神经网络实现

神经网络模型流程 神经网络模型的搭建流程&#xff0c;整理下自己的思路&#xff0c;这个过程不会细分出来&#xff0c;而是主流程。 在这里我主要是把整个流程分为两个主流程&#xff0c;即预训练与推理。预训练过程主要是生成超参数文件与搭设神经网络结构&#xff1b;而推理…

Redis集群:Sentinel哨兵模式(图文详解)

在 Redis 主从复制模式中&#xff0c;因为系统不具备自动恢复的功能&#xff0c;所以当主服务器&#xff08;master&#xff09;宕机后&#xff0c;需要手动把一台从服务器&#xff08;slave&#xff09;切换为主服务器。在这个过程中&#xff0c;不仅需要人为干预&#xff0c;…

vue3项目中前端导出word文档和导出excel文档

一、导出word文档 参考文章https://blog.csdn.net/qq_53722480/article/details/130017092 1、使用到的包如下&#xff1a; "docxtemplater": "^3.42.4", "file-saver": "^2.0.5", "jszip-utils": "^0.1.0", &q…

【分享】PDF文件不能编辑的3个原因

PDF文件具有很好的兼容性&#xff0c;可靠性&#xff0c;安全性&#xff0c;是很多人办公常用的电子文档格式。但有时候想要编辑PDF时&#xff0c;却发现不能编辑&#xff0c;是什么原因呢&#xff1f;下面小编来分享一下常见的3个原因。 原因1&#xff1a; PDF文件是扫描件&a…

6G网络将于2030年推出?它与5G相比都有哪些提升?

在这之前&#xff0c;我们曾为大家报道了苹果放弃5G调整解调器的研究工作「有消息称苹果将放弃 5G 调制解调器的研究&#xff0c;你了解调制解调器吗&#xff1f;」&#xff0c;如今又有报道称由于5G调整解调器开发遇到困难&#xff0c;苹果将加大对于6G蜂窝连接的开发。你知道…

第四届传智杯初赛(莲子的机械动力学)

题目描述 题目背景的问题可以转化为如下描述&#xff1a; 给定两个长度分别为 n,m 的整数 a,b&#xff0c;计算它们的和。 但是要注意的是&#xff0c;这里的 a,b 采用了某种特殊的进制表示法。最终的结果也会采用该种表示法。具体而言&#xff0c;从低位往高位数起&#xf…

GEE:构建和调用自己的 js 函数库

作者&#xff1a;CSDN _养乐多_ 本文记录了在Google Earth Engine&#xff08;GEE&#xff09;上构建自己的 js 函数库的步骤。构建自己的函数库以方便代码调用和扩展。 文章目录 一、创建lib文件二、调用lib库三、附加3.1 定义函数3.2 js 库中函数互相调用 一、创建lib文件 …