数据结构:排序趟数 / 比较次数与序列的原始状态有关的排序方法有哪些?「建议收藏」

数据结构:排序趟数 / 比较次数与序列的原始状态有关的排序方法有哪些?「建议收藏」先说结论比较次数与序列初态无关的算法是:二路归并排序、简单选择排序、基数排序比较次数与序列初态有关的算法是:快速排序、直接插入排序、冒泡排序、堆排序、希尔排序排序趟数与序列初态无关的算法是:直接插入排序、折半插入排序、希尔排序、简单选择排序、归并排序、基数排序排序趟数与序列初态有关的算法是:冒泡排序、快速排序关于排序趟数插入排序、选择排序趟数都是固定的n-1。对于插入排序来说或,即使序列有序,也要依次从第二个元素开始,向前找它的插入位置。冒泡排序趟数与数据有关,优

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

先说结论

比较次数 与序列初态 无关 的算法是:二路归并排序、简单选择排序、基数排序
比较次数 与序列初态 有关 的算法是:快速排序、直接插入排序、冒泡排序、堆排序、希尔排序

排序趟数 与序列初态 无关 的算法是:直接插入排序、折半插入排序、希尔排序、简单选择排序、归并排序、基数排序
排序趟数 与序列初态 有关 的算法是:冒泡排序、快速排序


关于排序趟数

插入排序、选择排序 趟数都是固定的 n-1。对于插入排序来说,即使序列有序,也要依次从第二个元素开始,向前找它的插入位置。

冒泡排序 趟数与数据有关,优化冒泡排序的最优复杂度为O(n),其主要优化就是记录了前一趟是否冒泡,如果没有产生冒泡就说明数组已经有序,直接return。如果产生了冒泡,才继续执行。

快速排序 的排序趟数就是它的递归深度。当 快排 的数据是有序时候,会退化为冒泡,所以快排趟数也与初始序列顺序有关了。如下图:

在这里插入图片描述


关于比较次数

有同学在评论中提出了疑问,我在这里补充一下吧,关于对于比较次数和初始状态的关系的理解
堆排序:比如元素下沉的操作,虽然一个元素是从底部拉上来的,但这不代表这个元素一定会接着沉到底部,如果沉到中间就停止下沉的话,比较次数就少了。而这个过程的比较次数自然和下沉的深度是相关的。
希尔排序:希尔排序是对简单插入排序的改进,每一趟希尔的内部使用的就是简单插入排序。而简单插入排序随着数据变成正序时,执行效率最好,每次插入都不用移动前面的元素,时间复杂度为O(N)。当数据是反序时,执行效率最差,此时时间复杂度为O(N*N). 类比到希尔排序中,希尔排序本身就是属于插入排序。当然会随着有序而少比较几次。
(这里说的比较次数是精确的次数,区别于时间复杂度的概念,时间复杂度只是描述了数量级)

选择排序

i 从头开始,每次遍历之后所有的元素,k 从 i 开始,向后标记 选出 最小的元素,循环后如果大于 i ,则与 i 位置元素 交换,一直到最后。
简单选择排序它最大的特点是,交换移动数据次数相当少,这样也就节约了相应的时间,无论最好最坏的情况,其比较次数都是一样多。第 i 次排序需要进行n-i 次关键字的比较,此时需要比较n-1+n-2+…+1=n(n-1)/2次,所以 总比较次数 与初始状态 无关,时间复杂度为O(n^2)。

对于交换次数而言,最差的时候,也就初始排序,交换次数为n-1次,复杂度为O(n)。当全部已经排序好时,则不发生交换,所以 元素总移动次数 与初始状态 有关

直接插入排序

从当前关键字之前的关键字开始扫描,如果大于待排关键字,则后移一位。直到全部记录插入完成。

如果全部有序,则只需要遍历一趟就完成了排序,比较次数为 n-1,并且在这个过程中没有发生元素的移动。因此,比较次数 与序列初态 有关 。初始序列基本有序时,移动元素最少(效率最高)。

在这里插入图片描述

void insertSort(int A[],int n)
{ 
   
        int i, j, temp;
        for (i = 1; i < n; i++) { 
    // 将各元素插入已经排好的序列中
            if (A[i] < A[i - 1]) { 
    // 若A[i]关键字小于前驱
                temp = A[i]; // 用 temp 暂存 A[i]
                for (j = i - 1; j >= 0 && A[j] > temp; --j) // 检查所有前面已经排好序的元素
                    A[j + 1] = A[j]; // 将所有大于 temp 的元素右移一个位置
                A[j + 1] = temp; // 复制到插入位置
            }
        }
}

若使用 折半插入 来进行优化,虽然减少了元素的比较次数,但并未使时间复杂度脱离O(n^2)


关于算法复杂度与序列初态的关系

算法复杂度 与初始状态 无关 的有哪些?

首先看内排序总结表:

在这里插入图片描述
由表中红线标出的地方可以轻易得出,以下四种排序方法的算法复杂度与数组的初始状态无关

一堆(堆排序)乌龟(归并排序)选(选择排序)基(基数排序)友。

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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/172511.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 前端工程师vscode必备插件(20个)

    前端工程师vscode必备插件(20个)阶段:前端新手只会html、css、js1.Chinese汉化vscode2.TokyoNightMaterialTheme已经下架了,这个是目前来说个人认为vscode中最好看的主题。3.vscode-icons文件的图标,这个是看着最顺眼的图标。4.prettier代码格式化工具,代码自动格式化。(需配置,最下面放上代码)如果安装了vetur,则会产生冲突,需要手动右键格式化,选择prettier。5.openinbrowser打开浏览器插件。

    2022年7月25日
    11
  • javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法

    javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法javascript数组以及对象的深拷贝(复制数组或复制对象)的方法前言在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝。如下图演示:如上,arr的修改,会影响arr2的值,这显然在绝大多数情况下,并不是我们所需要的结果。因此,数组以及对象的深拷贝就是javascript的一个基本功了。数组的深拷贝条条大道通罗马,实现数组的深拷贝,是有好几种方法的。举例如下:for循环

    2022年7月12日
    17
  • python lambda表达式详解

    python lambda表达式详解@pythonlambda表达式详解1、lambda简介先来看一段代码示例:第一行是lambda声明,x,y相当于传入的参数,整个函数会返回x+y的值。lambda作为一个表达式,定义了一个匿名函数,上例的代码x,y为入口参数,x+y为函数体。在这里lambda简化了函数定义的书写形式。python允许用lambda关键字创造匿名函数。匿名是不需要以标准的方式来声明,比如说使用def…

    2022年10月18日
    0
  • Android Studio IDE Out of Memory

    Android Studio IDE Out of Memory

    2022年1月22日
    49
  • java常见面试题及答案 11-20(JVM)

    11.JVM内存分哪几个区,每个区的作用是什么?java虚拟机主要分为以下一个区:方法区:1.有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载2.方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。3.该区域是被线程共享的。4.方法区里有

    2022年4月13日
    30
  • mysql分区表详解_详解MySQL分区表「建议收藏」

    mysql分区表详解_详解MySQL分区表「建议收藏」前言:分区是一种表的设计模式,通俗地讲表分区是将一大表,根据条件分割成若干个小表。但是对于应用程序来讲,分区的表和没有分区的表是一样的。换句话来讲,分区对于应用是透明的,只是数据库对于数据的重新整理。本篇文章给大家带来的内容是关于MySQL中分区表的介绍及使用场景,有需要的朋友可以参考一下,希望对你有所帮助。1.分区的目的及分区类型MySQL在创建表的时候可以通过使用PARTITIONBY子句定…

    2022年4月30日
    66

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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