排序算法基本原理及实现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;// 选择小的放入 extrawhile (i < mid && j < high) {// 加入等于,保证稳定性if (array[i] <= array[j]) {extra[k++] = array[i++];} else {extra[k++] = array[j++];}}// 将属于元素放入 extrawhile (i < mid) {extra[k++] = array[i++];}while (j < right) {extra[k++] = array[j++];}

时间复杂度

空间复杂度

O(n * log(n))

O(n)

数据不敏感

数据不敏感

// 从 extra 搬移回 arrayfor (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);}

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

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

相关文章

AI伪原创软件-AI伪原创工具下载

在当今数字化时代&#xff0c;创作者们在追求独特创意的同时&#xff0c;也面临着时间和灵感的双重挑战。AI伪原创技术应运而生&#xff0c;为创作者提供了一种快捷而便利的解决方案。本文将专心分享两款备受瞩目的AI伪原创工具&#xff0c;147SEO伪原创、百度文心一言伪原创&a…

数据结构-02-链表

相比数组&#xff0c;链表是一种稍微复杂一点的数据结构。掌握起来也要比数组稍难一些。这两个非常基础、非常常用的数据结构。 1-链表结构 数组需要一块连续的内存空间来存储&#xff0c;对内存的要求比较高。如果我们申请一个20MB大小的数组&#xff0c;当内存中没有连续的、…

串口理解小结(UART)

串口作为单片机的必备外设&#xff0c;主要用于单片机与其它模块的信息通讯、程序烧录和升级作用。 UART全称为通用异步收发器。 可分为&#xff1a; 一、串行和并行 串行指数据位只能一位一位地发送 并行之多个数据位同时发送 二、同步和异步 同步和异步是相当于时钟而…

【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

文章目录 行为型模式1、模板方法模式&#xff08;1&#xff09;概述&#xff08;2&#xff09;结构&#xff08;3&#xff09;案例实现&#xff08;4&#xff09;优缺点&#xff08;5&#xff09;适用场景&#xff08;6&#xff09;JDK源码解析&#xff08;7&#xff09;模板方…

用customize-cra+react-app-rewired配置less+css module

1. 安装 npm i less less-loader -D npm i customize-cra-less-loader -D2.添加配置项 //config-overrides.js const { override } require(customize-cra); const addLessLoader require("customize-cra-less-loader");module.exports {webpack: override(addL…

爬虫学习 逆向爬虫(六)

多任务异步协程 协程:更高效的利用CPU import timedef func():print("黎明")time.sleep(3)print("还是黎明")func() 等待时机长 sleep时CPU不再工作 IO操作(费时不费力)->阻塞 线程运行阻塞后 移出主线程 移动到下一个 4个任务一个线程 …

通用plantuml模板头

通用plantuml文件 startuml participant Admin order 0 #87CEFA // 参与者、顺序、颜色 participant Student order 1 #87CEFA participant Teacher order 2 #87CEFA participant TestPlayer order 3 #87CEFA participant Class order 4 #87CEFA participant Subject order …

微服务API网关Spring Cloud Gateway实战

概述 微服务网关是为了给不同的微服务提供统一的前置功能&#xff1b;网关服务可以配置集群&#xff0c;以承载更多的流量&#xff1b;负载均衡与网关互相成就&#xff0c;一般使用负载均衡&#xff08;例如 nginx&#xff09;作为总入口&#xff0c;然后将流量分发到多个网关…

线性表——(2)线性表的顺序存储及其运算的实现

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 看到美好&#xff0c;感受美好&a…

A*算法学习

系列文章目录 前言 在总结 2023华为软件精英挑战赛——全赛段思路分享与总结 - 知乎 (zhihu.com)时&#xff0c;发现自己还有很多技术细节没搞懂&#xff0c;这里看静态全局路径规划最常见的A*算法&#xff0c;这个博主讲得很好&#xff1a; A-Star&#xff08;A*&#xff0…

【ASP.NET CORE】.NET 6.0 NET CORE MVC连接SQLSERVER数据库

项目装NuGet包&#xff0c;具体版本如下 在appsettings.json中&#xff0c;添加连接字符串 代码如下&#xff1a; "ConnectionStrings": {"MVCSqlContext": "Serverlocalhost;DatabaseAddress;User IDsa;Passwordsa;TrustServerCertificatetrue&q…

5 面试题--redis

伪客户端&#xff1a; 伪客户端的 fd 属性值为 -1&#xff1b;伪客户端处理的命令请求来源于 AOF ⽂件或者 Lua 脚本&#xff0c;⽽不是⽹络&#xff0c;所以这种客户端不需要套接字连接&#xff0c;⾃然也不需要记录套接字描述符。⽬前 Redis 服务器会在两个地⽅ ⽤到伪客户端…