`
famoushz
  • 浏览: 2963142 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

比较排序算法——插入排序(Insertion Sort)

阅读更多


  插入排序的基本思想是,经过i-1遍处理后,L[1..i-1]己排好序。第i遍处理仅将L[i]插入L[1..i-1]的适当位置,使得 L[1..i]又是排好序的序列。要达到这个目的,我们可以用顺序比较的方法。首先比较L[i]和L[i-1],如果L[i-1]≤ L[i],则L[1..i]已排好序,第i遍处理就结束了;否则交换L[i]与L[i-1]的位置,继续比较L[i-1]和L[i-2],直到找到某一个 位置j(1≤j≤i-1),使得L[j] ≤L[j+1]时为止。图1演示了对4个元素进行插入排序的过程,共需要(a),(b),(c)三次插入。

图1 对4个元素进行插入排序

图1 对4个元素进行插入排序

   在下面的插入排序算法中,为了写程序方便我们可以引入一个哨兵元素L[0],它小于L[1..n]中任一记录。所以,我们设元素的类型 ElementType中有一个常量-∞,它比可能出现的任何记录都小。如果常量-∞不好事先确定,就必须在决定L[i]是否向前移动之前检查当前位置是 否为1,若当前位置已经为1时就应结束第i遍的处理。另一个办法是在第i遍处理开始时,就将L[i]放入L[0]中,这样也可以保证在适当的时候结束第i 遍处理。下面的算法中将对当前位置进行判断。

  插入排序算法如下:

  procedure Selection_Sort(var L:List);
  var
  i,j:position;
  v:ElementType;
  begin
  1 for i:=First(L)+1 to Last(L) do
      begin
  2     v:=L[i];
  3     j:=i;
  4     while (j<>First(L))and(L[j-1]< v) do  //循环找到插入点
          begin
  5         L[j]:=L[j-1];  //移动元素
  6         j:=j-1;
          end;
  7     L[j]:=v;  //插入元素
      end;
  end;

  下面考虑算法Insertion_Sort的复杂性。对于确定的i,内while循环的次数为O(i),所以整个循环体内执行了∑O(i)=O(∑i),其中i从2到n。即比较次数为O(n2 )。如果输入序列是从大到小排列的,那么内while循环次数为i-1次,所以整个循环体执行了∑(i-1)=n(n-1)/2次。由此可知,最坏情况下,Insertion_Sort要比较Ω(n2 )次。

   如果元素类型是一个很大的纪录,则算法第5行要消耗大量的时间,因此有必要分析移动元素的次数。经过分析可知,平均情况下第5行要执行n(n-1)/4 次,分析方法与冒泡排序的分析相同。如果移动元素要消耗大量的时间,则可以用链表来实现线性表,这样Insertion_Sort可以改写如下(当然前一 个算法同样也适用于链表,只不过没下面这个好,但是下面算法这个比较复杂):

  注意:在下面的算法中链表L增加了一个哨兵单元,其中的元素为-∞,即线性表L的第一个元素是L^.next^

  procedure Selection_Sort_II(var L:PList);
  var
  i,j,tmp:Position;
  begin
  1  if L^.next=nil then exit; //如果链表L为空则直接退出
  2  i:=L^.next;  //i指向L的第一个元素,注意,L有一个哨兵元素,因此L^.next^才是L的第一个元素
  3  while i^.next<>nil do
       begin
  4      tmp:=i^.next;  //tmp指向L[i]的下一个位置
  5      j:=L;
  6      while (j<>i)and(tmp^.data>=j^.next^.data) do //从前向后找到tmp的位置,tmp应该插在j后面
  7      j:=j^.next;
  8      if j<>i then  //j=i说明不需要改变tmp的位置
           begin    
  9          i^.next:=tmp^.next;  //将tmp从i后面摘除
  10         tmp^.next:=j^.next;  //在j后面插入tmp
  11         j^.next:=tmp;
           end
  12     else i:=i^.next;  //否则i指向下一个元素
      end;
  end;

  上述改进算法主要是利用链表删除和插入元素方便的特性,对于数组则不适用。

  插入排序法是一个原地置换排序法,也是一个稳定排序法。插入法虽然在最坏情况下复杂性为θ(n2 ),但是对于小规模输入来说,插入排序法是一个快速的原地置换排序法。许多复杂的排序法,在规模较小的情况下,都使用插入排序法来进行排序,比如快速排序和桶排序。

分享到:
评论

相关推荐

    常用排序算法——冒泡 选择 插入 快速

    一、插入排序(Insertion Sort) 插入排序是一种简单的排序算法。其基本思想是每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。 插入...

    图解插入排序-直接插入排序算法(straight insertion sort)

    图解插入排序——直接插入排序算法(straight insertion sort)

    排序算法总结——最全、最新的排序算法

    一、插入排序(Insertion Sort) 插入排序是一种简单的排序算法,它的基本思想是每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。 插入...

    多个排序算法的比较————C++

    3. **插入排序(Insertion Sort)** 插入排序将每个元素插入到已排序部分的正确位置。对于小规模或基本有序的数据,插入排序表现良好,但其平均和最坏情况下的时间复杂度都是O(n^2)。 4. **快速排序(Quick Sort)...

    数据结构算法源代码(插入排序和选择排序)

    在本文中,我们将深入探讨两种基础且重要的排序算法——插入排序和选择排序。这两种排序算法在数据结构和算法的学习中占据着核心地位,因为它们帮助初学者理解排序的基本原理。 首先,我们来看**插入排序...

    合并排序,插入排序,希尔排序,快速排序,冒泡排序,桶排序的C语言实现

    本文将详细讲解六种经典的排序算法——合并排序、插入排序、希尔排序、快速排序、冒泡排序以及桶排序,并结合提供的文件名(sort.c、set.c、main.c、set.h、sort.h)推测出每个文件可能包含的代码实现。 1. **合并...

    排序算法介绍——冒泡排序+插入排序+选择排序

    总结起来,冒泡排序、插入排序和选择排序都是基于比较的排序算法,它们在不同的场景下各有优劣。冒泡排序适用于小规模数据或接近有序的数据,插入排序在部分有序的数据上表现优秀,而选择排序则在内存限制的环境中...

    排序算法经典集锦(C、C#)

    本文将介绍两种经典的排序算法——直接插入排序和希尔排序,并分别提供C语言和C#语言的实现代码。 1. 直接插入排序 直接插入排序是一种简单的排序算法,其主要思想是通过逐步比较和移动元素来构建一个有序序列。它...

    排序算法的python实现

    本文将深入探讨两种常见的排序算法——插入排序(Insertion Sort)和快速排序(QuickSort)的Python实现。 首先,我们来看插入排序。插入排序是一种简单直观的排序算法,它的工作原理类似于我们日常生活中的整理...

    排序算法_java

    本文将深入探讨标题和描述中提及的五种经典排序算法——插入排序、归并排序、选择排序、冒泡排序和希尔排序,以及它们在Java中的实现。 1. 插入排序(Insertion Sort) 插入排序是一种简单直观的排序算法,它的工作...

    8种排序算法(选择排序 冒泡排序 快速排序等~)

    4. **插入排序(Insertion Sort)** 插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间...

    常见排序算法的实现与性能比较

    通过本实验,我们旨在实现六种常见的排序算法——合并排序、插入排序、希尔排序、快速排序、冒泡排序以及桶排序,并对它们的性能进行比较分析。 #### 实验原理简介 1. **合并排序**(Merge Sort) - **定义**:一...

    java实现的4种排序算法(冒泡、快速、插入、选择)

    以下是根据标题和描述中提到的四种排序算法——冒泡排序、快速排序、插入排序和选择排序的详细说明。 **冒泡排序(BuddleSort)**: 冒泡排序是一种简单的交换排序,它通过重复遍历待排序的列表,比较相邻元素并...

    c语言排序算法(插入,起泡,快速,选择)

    根据给定文件的信息,本文将详细介绍C语言中的四种基本排序算法——插入排序、起泡排序、快速排序和选择排序,并对这些算法进行深入解析。 ### 1. 插入排序 (Insertion Sort) 插入排序是一种简单直观的排序方法。...

    排序算法(Java描述)

    本文将深入探讨两种经典的排序算法——选择排序和插入排序,并通过Java语言进行具体描述,旨在帮助读者理解这两种算法的工作原理、时间复杂度以及实际应用。 #### 选择排序:效率与简洁性的权衡 选择排序是一种简单...

    数据结构六种内部算法排序比较

    根据给定文件的信息,本文将对六种不同的排序算法——冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序以及堆排序——进行详细分析,并比较它们之间的性能差异。 ### 冒泡排序(Bubble Sort) 冒泡排序...

    c#各种排序算法动态图形演示-数据结构经典算法动态演示

    2. 插入排序(Insertion Sort):插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。它在最好情况下(即输入数组已经部分排序)有很好的性能。 3. 选择排序...

    几种排序算法整理

    首先,让我们从最经典的排序算法——冒泡排序(Bubble Sort)开始。冒泡排序通过不断地交换相邻的不正确顺序的元素来逐步排序数组。它的主要步骤是遍历数组,比较每对相邻元素,如果顺序错误就交换它们。这个过程会...

    算法与数据结构课程设计——排序

    2. **直接插入排序**(Insertion Sort): 直接插入排序是将一个元素插入到已排序的部分序列中,以保持排序。每次插入都需要比较并可能移动元素。与冒泡排序类似,它的时间复杂度也为O(n^2),但当输入部分有序时,它...

    《Java数据结构和算法》学习笔记(2)——4种简单排序算法

    首先,我们来详细讲解插入排序(Insertion Sort)。插入排序的工作原理类似于我们手动整理扑克牌。我们从第一张牌开始,依次将后续的牌与已排序的部分比较,找到合适的位置插入。在Java实现中,我们可以用一个for...

Global site tag (gtag.js) - Google Analytics