插入排序

简介: 插入排序

Insertion Sort

对于近乎有序的数组,插入排序的时间复杂度优于O(nlogn)

对于完全有序数组,插入排序时间复杂度会降到O(n)

将待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

从头到尾依次扫描未排序序列,将扫描到的每个元素插入前面有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面)

和打扑克牌类似,手中的都是排好序的,抽到一张牌后,会插入到已排好序的牌中合适位置

从第二个元素开始,往前比较

算法步骤

template<typenameT>

voidinsertionSort(Tarr[],intn){

 //从第二个元素开始插入排序,直到末尾

   for(inti=1;i<n;i++){

       //从后往前比较,如果大于前面元素,说明是在合适位置,跳出当前循环

       for(intj=i;j>0;j--){

           if(arr[j]<arr[j-1])

               swap(arr[j],arr[j-1]);

           else

               break;

       }

   }

}

上述代码虽然可以提前终止内层循环,但是时间性能测试是没有选择排序快的

intmain(){

   intn=10000;

   //生成乱序数组

   int*arr=SortTestHelper::generateRandomArray(n,0,n);

   int*arr2=SortTestHelper::copyIntArray(arr,n);//复制arr得到arr2

   //测试耗时

   SortTestHelper::testSort("selectionSort",selectionSort,arr2,n);

   SortTestHelper::testSort("insertionSort",insertionSort,arr,n);

   //释放空间

   delete[] arr;

   delete[] arr2;

   return0;

}

/*

selectionSort : 0.16 s

insertionSort : 1.484 s

*/

优化

因为swap函数进行了三次赋值,赋值是比比较操作更加耗时的,可以减少赋值从而进行改进

先将要插入的元素存储起来,再将要插入的元素依次与前面的元素进行比较,小于前面元素的话,就将前面元素赋值到当前位置,直到要插入的元素大于等于前面元素。可以看到通过一次赋值替换了交换操作(三次赋值)

template<typenameT>

voidinsertionSortPlus(Tarr[],intn){

   //第一个元素显然有序,因此我们从第二个元素开始排序,若间隔为gap,则从下标为gap开始

   for(inti=1;i<n;i++){

       //记录要进行排序的元素

       Te=arr[i];

       //j是要插入的位置

       intj;

       for(j=i;j-1>=0;j=j-1){

           if(e<arr[j-1])

               arr[j]=arr[j-1];

<<<<<<<HEAD

           elsebreak;//明显当e>=arr[j-1]时跳出循环,说明arr[j]正是元素要插入的位置,而之前arr[j]已经后移一位

=======

           elsebreak;//明显当e>arr[j-1]时跳出循环,说明arr[j]正是元素要插入的位置,而之前arr[j]已经后移一位

>>>>>>>27c092bbe831973f875c92f374e0f8ec3ae3e3b4

       }

       arr[j]=e;

   }

}

selectionSort : 0.158 s

insertionSort : 0.113 s

当数据是近乎有序的,插入排序的时间复杂度甚至优于O(nlogn)

   // 生成一个近乎有序的数组,n是数组元素个数,swapTimes是指交换次数,因为数组要保持近乎有序

   int*generateNearlyOrderedArray(intn,intswapTimes){

       int*arr=newint[n];

       for(inti=0;i<n;i++)

           arr[i]=i;

       srand(time(0));

       for(inti=0;i<swapTimes;i++){

           intposx=rand()%n;

           intposy=rand()%n;

           swap(arr[posx],arr[posy]);

       }

       returnarr;

   }

intmain(){

   intn=10000;

   //生成近乎有序数组

   int*arr=SortTestHelper::generateNearlyOrderedArray(n,100);

   int*arr2=SortTestHelper::copyIntArray(arr,n);

   //测试耗时

   SortTestHelper::testSort("selectionSort",selectionSort,arr2,n);

   SortTestHelper::testSort("insertionSort",insertionSort,arr,n);

   //释放空间

   delete[] arr;

   delete[] arr2;

   return0;

}

selectionSort : 0.155 s

insertionSort : 0.003 s

目录
相关文章
|
1月前
|
搜索推荐 C++
C++插入排序的实现
C++插入排序的实现
|
3月前
|
存储 搜索推荐 算法
插入排序(一)——直接插入排序与希尔排序
插入排序(一)——直接插入排序与希尔排序
31 1
|
4月前
|
搜索推荐 算法 测试技术
排序算法:插入排序(直接插入排序、希尔排序)
排序算法:插入排序(直接插入排序、希尔排序)
37 0
|
5月前
|
搜索推荐
17 插入排序
17 插入排序
18 0
|
6月前
|
搜索推荐
插入排序
插入排序。
19 0
|
6月前
插入排序与希尔排序
插入排序与希尔排序
22 0
|
8月前
|
搜索推荐 测试技术 C++
【插入排序】直接插入排序 与 希尔排序
【插入排序】直接插入排序 与 希尔排序
|
10月前
|
算法
插入排序之直接插入排序
一、基本思想: 依次将每个记录(无序表)插入到一个已排好序的有序表中,得到一个新的,记录增加1的有序表;
|
人工智能 算法 搜索推荐
常见排序算法之插入排序——直接插入排序、希尔排序
哈喽大家好,我是保护小周ღ,本期为大家带来的是常见排序算法中的插入排序,主要有直接插入排序以及它的升级版——希尔排序,包您一看就会,快来试试吧~
114 0
常见排序算法之插入排序——直接插入排序、希尔排序
插入排序
在待排序的元素中,假设前n-1个元素已有序,现将第n个元素插入到前面已经排好的序列中,使得前n个元素有序。按照此法对所有元素进行插入,直到整个序列有序。   但我们并不能确定待排元素中究竟哪一部分是有序的,所以我们一开始只能认为第一个元素是有序的,依次将其后面的元素插入到这个有序序列中来,直到整个序列有序为止。