Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >经典算法学习之-----直接插入排序

经典算法学习之-----直接插入排序

作者头像
默 语
发布于 2024-11-20 01:41:39
发布于 2024-11-20 01:41:39
13500
代码可运行
举报
文章被收录于专栏:JAVAJAVA
运行总次数:0
代码可运行
直接插入排序 ​

🟡​一、什么是算法

算法是如何解决一类问题的明确规范,可以执行计算、数据处理、自动推理和其他任务。

️1.算法概念:

算法可以在有限的空间和时间内用定义明确的形式语言来表示,以计算函数。算法的一个典型例子是欧几里德算法,用于确定两个整数的最大公约数。在逻辑上,一个算法完成所需的时间是无法测量的,因为它与我们习惯的物理维度无关,这种不确定性导致无法找到既适合在某种意义上又适合抽象术语使用的算法定义。

算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间,空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。

算法中的指令描述的是一个计算,当其运行时能从一个初始状态和(可能为空的)初始输入开始,经过一系列有限而清晰定义的状态,最终产生输出并停止于一个终态。一个状态到另一个状态的转移不一定是确定的。随机化算法在内的一些算法,包含了一些随机输入。

算法的五大特征
有穷性(Finiteness)

算法的有穷性是指算法必须能在执行有限个步骤之后终止;

确切性(Definiteness)

算法的每一步骤必须有确切的定义;

输入项(Input)

一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条件;

输出项(Output)

一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的;

可行性(Effectiveness)

算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步骤,即每个计算步骤都可以在有限时间内完成(也称之为有效性)。

2.算法表达:

算法可用多种符号表示,包括自然语言、伪代码、流程图、drakon图表、编程语言或控制表。伪代码、流程图、drakon图表和控制表是表达算法的结构化方式,避免了自然语言语句中常见的许多歧义。编程语言主要用于以计算机可以执行的形式表达算法,但通常被用作定义或记录算法的一种方式。

3.计算机算法:

在计算机系统中,算法是软件开发人员用软件编写的逻辑实例, 使预定的“目标”计算机能够有效地从给定输入生成输出。一个最优算法,在旧硬件中运行,会比在更高效的硬件中运行的时间复杂度更高的算法产生更快的结果。

相信你也看过很多书上的定义,比如“算法是一组完成任务的指令”,“算法是操作数据的一组方法”。但是,你能举例说明吗?能让一个外行听明白吗?

它是什么

  • 计算机算法,是指前人提炼出高效的、不断被验证过的标准流程。

举例说明

你去书店,要买一本《人生故事》,你用什么方式找到这本书呢?

方式1:一本本的去找,估计会累瘫在书店。

方式2:使用电脑查询一下书所在的编号,比如202015,202表示2楼第2个分区,015表示第15个书架。你到2楼找到02分区,第15个书架,很快就找到了那本书。

以上两种方式都是可以称为算法:

  1. 使用方式1的流程:能找到但是非常的慢,而且费力。
  2. 使用方式2的流程:能快速的找到且省力。因为使用了 麦尔威·杜威发明的很多国家都在使用的杜威十进制图书分类法。

那么我们就可以得出 好的算法又快又省事; 使用的时间少,就是要快。 消耗的资源少,就是要省。

总结:概括的说,算法就是解决问题的工具。在描述一个算法时,我们关注的是输入与输出。也就是说只要把原始数据和结果数据描述清楚了,那么算法所做的事情也就清楚了。我们在设计一个算法时也是需要先明确我们有什么和我们要什么,这一点相信大家在后面的文章中会慢慢体会到。

扩展:
  1. 算法本质是一个流程,与生活中的做事的流程类似。
  2. 生活中算法与计算机算法中的区别:比较计算机算法数时,需要考虑数据量特别特别大,大到近乎无穷大的情况。 因为,计算机的发明就是用于处理大量数据的。
  3. 我们需要学习前人的算法,避免重复造轮子,站在巨人的肩膀上前进,才能走的更远。

4.数据结构

数据结构(Data Structure)是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。

数据结构定义 数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。记为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Data_Structure=(D,R) 

其中 D 是数据元素的集合,R 是该集合中所有元素之间的关系的有限集合。

数据结构具体指同一类数据元素中各元素之间的相互关系,包括三个组成成分,数据的逻辑结构、存储结构和数据运算结构。

数据的逻辑结构

数据的逻辑结构是指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关。逻辑结构分为以下几种:

集合结构:数据元素同属一个集合,单个数据元素之间没有任何关系。

线性结构:数据结构中的元素存在一对一的相互关系。

树形结构:数据结构中的元素存在一对多的相互关系。

图形结构:数据结构中的元素存在多对多的相互关系。 作者:

**那么为什么算法经常会和数据结构一起出现呢?**这是因为对于同一个问题(如:排序),使用不同的数据结构来存储数据,对应的算法可能千差万别。所以在整个学习过程中,也会涉及到各种数据结构的使用。 常见的数据结构包括:数组、堆、栈、队列、链表、树等等。

5.算法的效率

算法效率是指算法执行的时间,算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗的时间来度量。在现在的计算机硬件环境中,比较少需要考虑这个问题了,特别是pc机的编程,内存空间越来越大,所以被考虑得也越来越少,不过一个好的程序员,都应该对自己的程序有要求,每一个for比别人少一次判断1000个for就能够少掉很多的运行时间。所以能够理解,能够大概的去运用"效率度量"还是有很大意义的。

在我们日常开发中,一个算法设计完成后,还需要对算法的执行情况做一个评估。**一个好的算法,可以大幅度的节省运行的资源消耗和时间。**在进行评估时不需要太具体,毕竟数据量是不确定的,通常是以数据量为基准来确定一个量级,通常会使用到

时间复杂度和空间复杂度这两个概念。

二.时间和空间复杂度

1.时间复杂度

在计算机科学中,时间复杂性,又称时间复杂度,算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况。

通常把算法中的基本操作重复执行的频度称为算法的时间复杂度。算法中的基本操作一般是指算法中最深层循环内的语句(赋值、判断、四则运算等基础操作)。我们可以把时间频度记为T(n),它与算法中语句的执行次数成正比。其中的n被称为问题的规模,大多数情况下为输入的数据量。

对于每一段代码,都可以转化为常数或与n相关的函数表达式,记做f(n) 。如果我们把每一段代码的花费的时间加起来就能够得到一个刻画时间复杂度的表达式,在合并后保留量级最大的部分即可确定时间复杂度,记做O(f(n)) ,其中的O就是代表数量级。

常见的时间复杂度有(由低到高):O(1)、O( log ⁡ 2 n \log _{2} n log2​n)、O(n)、O( n log ⁡ 2 n n\log _{2} n nlog2​n)、O( n 2 n^{2} n2)、O( n 3 n^{3} n3)、O( 2 n 2^{n} 2n)、O(n!)。

四个时间复杂度

同一段代码在不同输入的情况下,可能存在时间复杂度量级不一样的情况,所以有以下四种不同的时间复杂度。

  • 最好情况时间复杂度(best case time complexity);
  • 最坏情况时间复杂度(worst case time complexity);
  • 平均情况时间复杂度(average case time complexity);
  • 均摊时间复杂度(amortized time complexity)。
1、最好、最坏、平均情况时间复杂度
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// n表示数组array的长度
int find(int *array, int n, int x) {
  int i = 0;
  int pos = -1;
  for ( ; i < n; ++i) {
    if (array[i] == x) {
       pos = i;
       break;
    }
  }
  return pos;
}

这是一个find()函数,这段代码的作用是查找参数x在数组array中的位置,如果没有就返回-1。

最好情况时间复杂度: 在最理想的情况下,代码的时间复杂度。本例中,如果数组中的第一个元素就是要查找的变量,则时间复杂度为O(1)。

最坏情况时间复杂度: 在最糟糕的情况下,代码的时间复杂度。本例中,如果数组中没有变量x,则需要遍历数组中的每一个元素,则时间复杂度为O(n)。

平均情况时间复杂度: 最好、最坏情况时间复杂度表示的都是代码在极端情况下的时间复杂度,发生的概率并不大,所以平均情况时间复杂度用于表示平均情况下的时间复杂度。

本例中,首先,变量x分为在数组中和不在数组中两种情况,假设两种情况的概率相同为

在这里插入图片描述
在这里插入图片描述

;其次,要查找的变量出现在数组0 ~ n-1共n个位置的概率是一样的,都为

;最后,根据概率论的知识,变量x出现在0 ~ n-1这n个位置的概率都为

,变量不在数组中的概率为

。 根据概率论中的加权平均值,也叫期望值的计算放法(每一种情况下的时间复杂度乘以其发生的概率)得出平均时间复杂度的值:

用大O表示法表示,则平均时间复杂度为O(n),所以平均时间复杂度又叫加权平均时间复杂度,或者期望时间复杂度。

一般情况下,我们并不会区分这三种时间复杂度,只使用其中一种即可。当同一代码块在不同情况下的时间复杂度有量级上的差距,才会区分这三种复杂度。

2、均摊时间复杂度

由上述可知,一般情况下,并不区分最好、最坏、平均情况时间复杂度,平均情况时间复杂度也只有在某些特殊的情况下才会使用,而均摊时间复杂度的应用场景比平均复杂度更特殊,更有限。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// array表示一个长度为n的数组
// 代码中的array.length就等于n
int *array = new int[n];
int count = 0;
 
void insert(int val) {
   if (count == array.length) {
      int sum = 0;
      for (int i = 0; i < array.length; ++i) {
         sum = sum + array[i];
      }
      array[0] = sum;
      count = 1;
   }

   array[count] = val;
   ++count;
}

这是一个insert()函数,实现往数组中插入一个数据的功能,如果数组满了的话,即当count == array.length时,遍历数组求和,并把数据放到数组第一个位置,然后再把新的数据插入。

本段代码的时间复杂度分析:

最好情况时间复杂度:数组未满,有空闲的位置时为O(1); 最坏情况时间复杂度:数组已满,需要遍历求和时为O(n); 平均情况时间复杂度:分为数组未满和已满两种情况,未满时的插入有n种情况,每种情况的时间复杂度为O(1),已满时的时间复杂度度为O(n),所以共n+1种可能,这n+1种可能的概率相同都是

,所以平均情况时间复杂度为:

2)、均摊时间复杂度

  • 本例中的insert()函数区别于之前的find()函数:find()函数在极端情况下,时间复杂度为O(1),而insert()函数在大多数情况下时间复杂度都为O(1);find()函数时间复杂度的多种情况并没有任何规律。而insert()函数O(n)之后,必有n-1个O(1),循环往复。
  • 针对这种特殊的场景,可以采用一种特殊的时间复杂度分析方法:摊还分析法,得出的是均摊时间复杂度。
  • 分析方法: 因为时间复杂度有规律的在O(n) -> n-1个O(1)之间循环,所以把耗时最多的那次操作(O(n)),均摊到耗时最少的n-1次操作(O(1)),这样,每一组操作的时间复杂度都是O(1),即均摊时间复杂度为O(1)。
  • 应用场景: 均摊时间复杂度就是一种特殊的平均情况时间复杂度,没有必要过度区分。当大部分情况下的时间复杂度较低,而只有极少数情况下的时间复杂度较高,且这些情况的出现有固定的时序性规律时,使用均摊时间复杂度。这时,尝试将较高复杂度操作的耗时均摊到较低复杂度的操作上,这就叫摊还分析法。

一般能应用摊还分析法的场景,均摊时间复杂度就等于最好情况时间复杂度

2.空间复杂度

程序从开始执行到结束所需要的内存容量,也就是整个过程中最大需要占用多少的空间。为了评估算法本身,输入数据所占用的空间不会考虑,通常更关注算法运行时需要额外定义多少临时变量或多少存储结构。如:如果需要借助一个临时变量来进行两个元素的交换,则空间复杂度为O(1)。

时间复杂度

最坏的情况

最坏的情况就是完整的遍历了整个集合,也并未找到目标的key,此时循环被完整的执行,循环执行次数与n相关,所以时间复杂度为O(n) 。

最好的情况

最好的情况就是第一次就找到了元素,此时的时间复杂度为常数级O(1) 。

平均情况

综合两种情况,顺序查找的时间复杂度为O(n) ,属于查找较慢的算法。

3. 空间复杂度 由于算法不会改变原有的元素集合,只需要一个额外的变量控制索引变化,所以空间复杂度为常数级:O(1) 。

空间复杂度涉及的空间类型有

输入空间: 存储输入数据所需的空间大小; 暂存空间: 算法运行过程中,存储所有中间变量和对象等数据所需的空间大小; 输出空间: 算法运行返回时,存储输出数据所需的空间大小;

通常情况下,空间复杂度指在输入数据大小为 N 时,算法运行所使用的「暂存空间」+「输出空间」的总体大小

而根据不同来源,算法使用的内存空间分为三类:

指令空间: 编译后,程序指令所使用的内存空间。

数据空间: 算法中的各项变量使用的空间,包括:声明的常量、变量、动态数组、动态对象等使用的内存空间。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct Node {
    int val;
    Node *next;
    Node(int x) : val(x), next(NULL) {}
};
 
void algorithm(int N) {
    int num = N;              // 变量
    int nums[N];              // 动态数组
    Node* node = new Node(N); // 动态对象
}

栈帧空间: 程序调用函数是基于栈实现的,函数在调用期间,占用常量大小的栈帧空间,直至返回后释放。如以下代码所示,在循环中调用函数,每轮调用 test() 返回后,栈帧空间已被释放,因此空间复杂度仍为 O(1)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int test() {
    return 0;
}
 
void algorithm(int N) {
    for (int i = 0; i < N; i++) {
        test();
    }
}

算法中,栈帧空间的累计常出现于递归调用。如以下代码所示,通过递归调用,会同时存在 N 个未返回的函数 algorithm() ,此时累计使用 O(N) 大小的栈帧空间。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int algorithm(int N) {
    if (N <= 1) return 1;
    return algorithm(N - 1) + 1;
}

根据从小到大排列,常见的算法空间复杂度有:

O(1) < O(logN) < O(N) < O(N^2) < O(2^N)

只做简单概念简读;具体可查看 博客

三.插入排序介绍

插入排序的基本思路是每次插入一个元素,每一趟完成对一个待排元素的放置,直到全部插入完成。

直接插入排序

直接插入排序是一种最简单的排序方法,过程就是将每个待排元素逐个插入到已经排好的有序序列中。

折半插入排序

由于在插入排序的过程中,已经生成了一个(排好的元素组成的)有序数列。所以在插入待排元素时可以使用折半查找的方式更快速的确定新元素的位置,当元素个数较多时,折半插入排序优于直接插入排序。

希尔排序 希尔排序可以看做是分组插入的排序方法,把全部元素分成几组(等距元素分到一组),在每一组内进行直接插入排序。然后继续减少间距,形成新的分组,进行排序,直到间距为1时停止。

四. 直接插入排序

输入

n个数的序列,通常直接存放在数组中,可能是任何顺序。

输出

输入序列的一个新排列,满足从小到大的顺序(默认讨论升序,简单的修改就可以实现降序排列)。

算法说明

每次从原有数据中取出一个数,插入到之前已经排好的序列中,直到所有的数全部取完,那么新的有序排列也就完成了。 通俗一点的解释就是好比我们在打扑克抓牌,所有的牌扣在桌面上,我们一张一张的抓,抓起一张就在手里把它排好。那么等我们把所有的牌都抓起来之后,手里的牌也都是有序的了。

算法流程

对于计算机来说,我们必须要详细的告诉它如何比较大小,以及如何确定位置,毕竟它不能像我们一样,“一眼”就看出位置。试想一下,当数据量比较多的时候,我们也是需要一个一个的看过来,然后才能确定新插入元素的位置。

第一个元素:放在第一个位置,直接排好 第二个元素:与第一个元素比较,如果更大,放在第二个位置,如果更小,放在第一个位置 第三个元素:顺次从后向前比较,如果更小,将已排好元素向后串位,最后插入第三个元素 剩余其他元素:顺次从后向前比较,如果更小,将已排好元素向后串位,直到找到合适的位置插入 如果待排元素是已排好的元素中最大的,只需要比较一次,然后直接追加到已排好的序列后面

四. 伪代码

直接插入排序是一个比较好理解的算法,大家直接用抓牌就可以完美刻画:每次摸起一张牌,从右至左(从大到小)的与手中的牌比较,如果摸起来的这张是手牌里最大的,就直接放在最右边,如果不是最大的,就顺次滑过比它大的牌(相当于串位),直到遇见一个比刚摸起这张牌小的手牌,插入到这张牌的后面。 按照这样的步骤重复操作,当所有的牌都被抓完时,手里的牌就都是有序的了,理解了算法的思路后,我们用伪代码来进行表示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for j = 2 to A.length
    key = A[j]
    i = j - 1
    while i > 0 and A[i] > key
        A[i + 1] = A[i]
        i = i - 1
    A[i + 1] = key

初始计数器为2,代表第一个元素默认排好,从第二个元素开始操作,直到最后一个元素。 每次用key记录新操作的元素,i的初始值代表当前操作元素的前一个元素,也就是第一个要与之比较的元素。 while循环为内层循环,作用是在已排好的元素中找到合适的位置,来将key插入。 如果进入到循环体中执行,代表key相对较小,还要再向前寻找,同时,与之比对的元素要向后串位,因为此时可以确定,key一定在这个元素的前面,在进入下一次循环时,使用再前面一位的元素进行比对。 for循环的最后一行是将key插入到对应的位置,外层循环结束(每次循环插入一个数)。

五:算法实践

1. 算法实现

输入数据(input):11,34,20,10,12,35,41,32,43,14 Java源代码 需要注意源代码与伪代码的区别,请查看文章开头补充的概念部分,这里不做过多说明。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DirectInsert {

    public static void main(String[] args) {
        // input data
        int[] a = {11,34,20,10,12,35,41,32,43,14};
        // 数组下标从0开始,j初始为1,指向第二个元素
        for (int j = 1;j < a.length;j++){
            // 使用key记录当前元素的值
            int key = a[j];
            // 初始化i,为j的前一个元素
            int i = j - 1;
            // while循环作用:在已经排好的有序数列中确定key的位置,并串出对应的位置
            while(i >= 0 && a[i] > key){
                // 串位覆盖,不需要使用交换,值已经被记录在key中
                a[i + 1] = a[i];
                // 逐渐前移
                i = i - 1;
            }
            // 将待排元素放在对应的位置
            a[i + 1] = key;
        }
        // 查看排序结果
        for (int data : a){
            System.out.print(data + "\t");
        }
    }

}

执行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输出数据(output):10111214203234354143
2. 时间复杂度

最坏的情况

最坏的情况就是指每一行代码都被执行了,循环也是被完全拉满的情况,一次都没有少,确实很充实很悲催了。 对于直接插入排序来说,如果输入的元素刚好是反向有序的,那么每次取出一个元素,都要和已经排好的每一个元素进行比较,直到比较到第一个元素,然后把自己放在最前面,没办法,每次拿到的都是比之前小的元素,好气哦。 在这种情况下,内层while循环中的代码一共执行了 ∑ i = 1 n − 1 i = n ( n − 1 ) 2 = O ( n 2 ) \sum_{i=1}^{n-1} i=\frac{n(n-1)}{2}=O\left(n^{2}\right) ∑i=1n−1​i=2n(n−1)​=O(n2),其中n为输入的数据个数。 在计算时间复杂度时,我们只关心最后的量级就好,比如for循环中代码以及while循环中的代码都有多行,最后的结果一定比 n 2 n^{2} n2大,但都是属于O( n 2 n^{2} n2) 。

最好的情况

最好的情况就是指能不被执行的步骤都没有被执行,来的数据刚刚好,并且每个数据都是这样,简直就是天选之人。 对于直接插入排序来说,如果输入的元素已经是正向有序的,那么每次取出一个元素,在和已经排好的序列中的最后一个元素比较之后,就可以直接放到后面,循环都不用进,因为已经找到了它应该在的位置。 在这种情况下,内层的while循环可以只看成一个判断语句了,嗯,就是这样。所以代码执行的次数主要看外层for循环就好了,一共是n-1次,属于O(n) 。

平均情况

综合两种情况,插入排序的时间复杂度为O( n 2 n^{2} n2) 。

3. 空间复杂度

除计数器以外,算法执行过程中需要使用临时变量key来记录一下当前元素的值,除此之外的其他操作都可以在原数据结构(数组)上完成,所以空间复杂度为O(1) 。

部分文章来自;1,2,3

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
经典算法——直接插入排序
任何被明确定义的计算过程都可以称作 算法 ,它将某个值或一组值作为输入,并产生某个值或一组值作为输出。所以 算法可以被称作将输入转为输出的一系列的计算步骤 。
鱼找水需要时间
2023/02/16
4160
经典算法——直接插入排序
经典算法学习之---折半插入排序
本专栏为《手撕算法》栏目的子专栏:《经典算法》,会讲述一些经典算法,并进行分析。在此之前我们要先了解什么是算法,能够解决什么样的问题。
默 语
2024/11/20
1710
经典算法学习之---折半插入排序
【排序算法篇】---直接插入排序
直接插入排序是一种常见而简单的排序算法,其基本思想是将待排序的元素插入到一个已经排好序的有序序列中,从而生成一个新的有序序列。排序的过程可以被视为将待排序的数组分成两个部分:已排序部分和未排序部分。在每一步中,从未排序部分取出一个元素,并将其插入到已排序部分的适当位置,直到所有元素均被插入为止。 具体的实现步骤如下:
意疏
2024/11/25
2220
【排序算法篇】---直接插入排序
直接插入排序
登鹳雀楼 唐·王之涣 白日依山尽,黄河入海流。  欲穷千里目,更上一层楼。 面试官:聊聊插入排序 插入排序是一种比较简单直观的排序算法,适用处理数据量比较少或者部分有序的数据,今天我们来聊聊插
用户1260737
2018/03/26
7850
直接插入排序
小朋友学数据结构-10大排序算法(2):直接插入排序
在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。 举例:数组a[] = {57, 68, 59, 52}。 比较方法是每个数与前面的数比较。 第一个57,前面没有数,不用比较。 第二个数68,与前面的57比较,因为68 > 57,所以不用换位置。 第三个数59,先与前面的68比较,因为59 < 68,所以需要与更前面的数57比较,因为59 > 57。所以无论57的前面有没有数,都不用再比较了。把59插入到57和68之间就可以了。 第四个数52,前面有三个数:57,59,68。先与68比,52 < 68,需要再与59比,52 < 59,需要再与57比,52 < 57。此时前面没有数了。所以把52插入到57的前面。 最终的结果为52,57,59,68。
海天一树
2018/12/26
3830
插入排序之直接插入排序
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
suveng
2019/09/18
4270
插入排序之直接插入排序
经典算法——折半插入排序
任何被明确定义的计算过程都可以称作 算法 ,它将某个值或一组值作为输入,并产生某个值或一组值作为输出。所以 算法可以被称作将输入转为输出的一系列的计算步骤 。
鱼找水需要时间
2023/02/16
6140
经典算法——折半插入排序
直接插入排序和直接选择排序
直接插入排序的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的序列中的适当位置,直到全部记录插入完成为止。
创译科技
2019/06/02
3.7K0
经典算法学习之-----希尔排序
本专栏为《手撕算法》栏目的子专栏:《经典算法》,会讲述一些经典算法,并进行分析。在此之前我们要先了解什么是算法,能够解决什么样的问题。
默 语
2024/11/20
1240
经典算法学习之-----希尔排序
排序1:直接插入排序
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。 这一点就类似于我们打扑克的时候把一张牌插入到其他牌的前面。
青衫哥
2023/03/31
2530
排序1:直接插入排序
【排序算法】——插入排序
所谓排序算法,即通过特定的算法因式将一组或多组数据按照既定模式进行重新排序。这种新序列遵循着一定的规则,体现出一定的规律,因此,经处理后的数据便于筛选和计算,大大提高了计算效率。对于一个排序算法的优劣,我们需要从它的时间复杂度、空间复杂度和稳定性三个方面来考虑。什么叫稳定性呢?即当两个相同的元素同时出现于某个序列之中,则经过一定的排序算法之后,两者在排序前后的相对位置不发生变化。换言之,即便是两个完全相同的元素,它们在排序过程中也是各有区别的。
code_monnkey_
2025/05/31
1050
【排序算法】——插入排序
【数据结构】排序算法---直接插入排序(动图演示)
直接插入排序是一种简单直观的排序算法。它的工作原理为将待排列元素划分为「已排序」和「未排序」两部分,每次从「未排序的」元素中选择一个插入到「已排序的」元素中的正确位置。
Crossoads
2024/10/22
4890
【数据结构】排序算法---直接插入排序(动图演示)
7.2.1 直接插入排序
插入排序是一种简单直观的排序方法,其基本思想在于每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列,直到全部记录插入完成。
week
2018/08/27
5140
程序猿修仙之路--算法之插入排序
在算法时间复杂度维度,我们主要对比较和交换的次数做对比,其他不交换元素的算法,主要会以访问数组的次数的维度做对比。
架构师修行之路
2019/07/23
3620
程序猿修仙之路--算法之插入排序
【初探数据结构】直接插入排序与希尔排序详解
插入排序是一种简单直观的排序算法,核心思想是:将数组分为“已排序”和“未排序”两部分。每次从未排序部分取出第一个元素,将其插入到已排序部分的正确位置,直到所有元素有序。
我想吃余
2025/03/31
1640
【初探数据结构】直接插入排序与希尔排序详解
数据结构从入门到精通——直接插入排序
直接插入排序是一种简单的排序算法,其工作原理是逐个将待排序元素插入到已排序序列中的适当位置,直到全部元素排序完毕。算法从第二个元素开始,将其与前面的元素进行比较,如果当前元素小于前一个元素,则将其插入到前一个元素之前,否则继续向前比较。重复此过程,直到当前元素找到合适的插入位置。每次插入一个元素后,已排序序列的长度增加1,直到整个序列排序完成。直接插入排序的时间复杂度为O(n^2),在数据量较小时效率较高,但在大规模数据排序中性能不佳。
鲜于言悠
2024/03/24
8350
数据结构从入门到精通——直接插入排序
数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 数据结构图文解析之:树的简介及二叉排序树C++模板实现. 数据结构图文解析之:AVL树详解及C++模板实现 数据结构图文解析之:二叉堆详解及C++模板实现 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现 数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现 数据结构图文解析之:
Tencent JCoder
2018/07/02
1.5K0
直接插入排序到希尔排序做的那些改进
主要推送关于对算法的思考以及应用的消息。坚信学会如何思考一个算法比单纯地掌握100个知识点重要100倍。本着严谨和准确的态度,目标是撰写实用和启发性的文章,欢迎您的关注,让我们一起进步吧。 01 — 你会学到什么? 彻底弄明白常用的排序算法的基本思想,算法的时间和空间复杂度,以及如何选择这些排序算法,确定要解决的问题的最佳排序算法,已经总结了冒泡排序和其改进后的快速排序算法,直接选择排序和堆排序算法,下面总结直接插入排序到希尔排序做的改进,后面再继续总结归并排序和基数排序。 02 — 讨论的问题是什么? 各
double
2018/04/02
9880
直接插入排序到希尔排序做的那些改进
经典算法学习之-----直接选择排序
算法可以在有限的空间和时间内用定义明确的形式语言来表示,以计算函数。算法的一个典型例子是欧几里德算法,用于确定两个整数的最大公约数。在逻辑上,一个算法完成所需的时间是无法测量的,因为它与我们习惯的物理维度无关,这种不确定性导致无法找到既适合在某种意义上又适合抽象术语使用的算法定义。
默 语
2024/11/20
960
经典算法学习之-----直接选择排序
排序算法-插入排序
算法简介 插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因为在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。 算法描述 从第一个元素开始,该元素可以认为已经被排序 取出下一个元素,在已经排序的元素序列中从后向前扫描 如果该元素(已排序)大于新元素,将该元素移到下一位置 重复步骤
武培轩
2018/04/18
6160
排序算法-插入排序
相关推荐
经典算法——直接插入排序
更多 >
交个朋友
加入腾讯云技术交流站
洞悉AI新动向 Get大咖技术交流群
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验