十大排序算法小结

十大排序算法小结

相关博客:

排序算法:冒泡排序、插入排序、选择排序、希尔排序

排序算法:归并排序、快速排序

排序算法:桶排序、计数排序、基数排序

排序算法:堆排序


 

前面学习了10中最基本的排序算法,这篇博客主要是对这10种排序算法的小结:

1、这十种排序算法可以分为两大类:

(1)非线性时间排序算法:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序。这类算法包括:冒泡排序、插入排序、选择排序、希尔排序、归并排序、快速排序、堆排序。

(2)线性时间非比较类排序算法:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。 这类算法包括:桶排序、计数排序、基数排序。不过,虽然这几种算法的时间复杂度比较低,但是他们对要排序的数据要求也比较苛刻。

2、复杂度分析: 

  排序方法 最好时间复杂度 最坏时间复杂度 平均时间复杂度 空间复杂度 稳定性

非线性

时间排

序算法

冒泡排序 O(n) O(n^2) O(n^2) O(1) 稳定
插入排序 O(n) O(n^2) O(n^2) O(1) 稳定
选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定
希尔排序 O(n) O(n^2) O(n^1.3) O(1) 不稳定
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定
快速排序 O(nlogn) O(n^2) O(nlogn) O(1) 不稳定
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定

线性时间

排序算法

桶排序 O(n) O(n^2) O(n) O(n+k) 稳定
计数排序 O(n+k) O(n+k) O(n+k) O(n+k) 稳定
基数排序 O(n*k) O(n*k) O(n*k) O(n+k) 稳定
其中k为桶的数量

 

二、算法主要思想:

1、冒泡排序:

冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系的要求。如果不满足就让它俩互换位置。一次冒泡会让至少一个元素移动到它应该在的位置,重复n次,就完成了n个数据的排序工作。

2、插入排序:

将数组的数据分为两个区间,已排序区间和未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素。算法的核心思想就是,取未排序区间中的元素,在已排序区间中找到合适的位置将其插入,并保证已排序区间的数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束。

3、选择排序:

选择排序的实现思路和插入排序类似,也分为已排序区间和未排序区间。但是选择排序每次会从未排序区间中选择最小(最大)的元素,存放已排序区间的末尾。重复此操作,直到所有元素排序完毕。

上面三种排序的时间复杂度都是O(n^2),比较高,适合小规模数据的排序。

4、希尔排序:

希尔排序是简单插入排序的改进版。他与插入排序的不同之处在于,它会优先比较较远的元素。希尔排序又叫缩小增量排序。希尔排序的核心在于间隔序列的设定(也就是增量)。既可以提前设定好间隔序列,也可以动态定义间隔序列。

5、归并排序:

归并排序的采用分治思想,如果要排序一个数组,我们先把数组从中间分成前后两个部分,然后对前后两个部分分别进行排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。核心是merge()合并函数。

6、快速排序:

快速排序也是利用分治思想。如果要排序一组数据,我们先选择这组数据中任意一个数据作为分区点pivot,然后遍历这组数据,将小于分区点pivot的放到左边,大于分区点pivot的放到右边,将pivot放到中间。然后再分别对左右两部分进行排序。核心是partition()函数。

7、堆排序:

堆排序是指利用堆这种数据结构进行排序的一种算法,堆排序分为建堆和排序两大步骤。堆需要满足一下两个特性:

①堆是一种完全二叉树,也就是除了最后一层,其他层的节点个数都是满的,最后一个节点都靠左排列。所以可以使用数组来存储堆中每个节点的值

②堆中每一个节点的值都必须大于等于(或小于等于)其左右子节点的值。

(1)首先对要排序的数据进行建堆。建堆结束后,数组中的数据已经是按照大顶堆的特性组织的。数组中的第一个元素就是堆顶(即最大值)。

(2)将堆顶元素a[1]与最后一个元素a[n]交换,这时,最大元素就放到了下标为n的位置。

(3)重新堆化:交换后新的堆顶可能违反堆的性质,需要重新进行堆化。

(4)重复(2)(3)操作,直到最后堆中只剩下下标为1的元素,排序就完成了。

8、桶排序:

桶排序的核心思想就是将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。桶排序完之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。

适用场景:首先,要排序的数据需要很容易就能划分成m个桶,并且,桶与桶之间有着天然的大小顺序。这样每个桶内数据都排序完之后,桶与桶之间的数据不需要在进行排序。其次,数据在各个桶之间的分布比较均匀的。所以,桶排序比较适合用在外部排序中。所谓的外部排序就是数据存储在外部磁盘中,数据量比较大,内存有限,无法将数据全部加载到内存中。

9、计数排序:

计数排序可以看成是桶排序的一种特殊情况,只是桶的大小粒度不一样。当要排序的 n 个数据,所处的范围并不大的时候,比如最大值是 k,我们就可以把数据划分成 k 个桶。每个桶内的数据值都是相同的,省掉了桶内排序的时间。

适用场景:计数排序只能用在数据范围不大的场景中,如果数据范围 k 比要排序的数据 n 大很多,就不适合用计数排序了。而且,计数排序只能给非负整数排序,如果要排序的数据是其他类型的,要将其在不改变相对大小的情况下,转化为非负整数。

10、基数排序:

基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。基数排序对要排序的数据是有要求的,需要可以分割出独立的“位”来比较,而且位之间有递进的关系,如果 a 数据的高位比 b数据大,那剩下的低位就不用比较了。除此之外,每一位的数据范围不能太大,因为基数要借助桶排序或者计数排序算法来排序,否则,基数排序的时间复杂度就无法做到 O(n) 了。

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114616.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 深入浅出谈开窗函数(一)

    深入浅出谈开窗函数(一)

  • 反射入门_入门教程

    反射入门_入门教程反射package com.atguigu.java;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Person { private String name; public int age; public Person() { } public void setName(S

  • C语言链表排序_C语言版数据结构链表

    C语言链表排序_C语言版数据结构链表以上搬运至郝斌老师数据结构中的视频知识,然后依样画葫芦去写的;当然指针知识和链表的基础知识要先懂:首先先创建链表,如下:typedef struct node{intdata;//创建数据域structnode*pNext;//创建指针域}NODE,*PNODE;//相当于structnode,struct*nodePNODE

  • Linuxstat_linux内核编译的基本流程

    Linuxstat_linux内核编译的基本流程stat函数讲解:表头文件:#include#include定义函数:intstat(constchar*file_name,structstat*buf);函数说明:通过文件名filename获取文件信息,并保存在buf所指的结构体stat中返回值:执行成功则返回0,失败返回-1,错误代码存于errno错误代码:ENOENT参数file_name指定的文件不存在ENOT…

  • PLANTINUM_plantuml流程图

    PLANTINUM_plantuml流程图bytotinunsplash1.背景随着工作时间的增长,越发觉得用专业的图形(用例图,时序图,ER图等等)去准确表达想法是很重要的。比如针对某个需求绘制的的用例图,比一段乏味的文字来的更加有意义,也便于别人理解。加之最近在学习源码的时候,发现很多书籍中都会使用类图,时序图等UML语言来描述逻辑关系。于是就在网上找了找绘制UML语言时,业界主流的一些工具都用什么,找了半天,大部分都用了下面…

    2022年10月26日
  • NOIP-铺地毯_zamani地毯

    NOIP-铺地毯_zamani地毯NOIP-铺地毯

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号