-
插入排序算法
2017-10-14 13:43:28插入排序算法 一个对少量元素进行排序的有效算法 待排序的数也叫关键字(key)插入排序算法
一个对少量元素进行排序的有效算法
待排序的数也叫关键字(key)
思路:从数组中的第二个元素开始,依次将后面的成员设置为key。当前的key与之前的成员进行比较,如果该成员大于key,就将该成员向后移,直到成员比当前的key小或者到数组的”头”。
/*插入排序算法 *输入:数组名和数组长度 *完成后返回0 */ int HinsertionSort(int *array,int count) { int i,j; for(i=1;i<count;i++) { j=i-1; int key=*(array+i); while(j>=0&&*(array+j)>key) { *(array+j+1)=*(array+j); j--; } *(array+j+1)=key; } return 0; }
-
插入排序 算法
2012-11-21 08:36:46今天,整理一下插入排序, 其实一天掌握一种排序也不错, 毕竟算法是思考与理解性的东西。一次性能听懂,但基本都是当时懂了,过几天就没有办法重现了,这点至少对于我来说,在学习二叉树是体现的尤为明显。 ...今天,整理一下插入排序, 其实一天掌握一种排序也不错, 毕竟算法是思考与理解性的东西。一次性能听懂,但基本都是当时懂了,过几天就没有办法重现了,这点至少对于我来说,在学习二叉树是体现的尤为明显。
大家都知道,只有一个数时不用排序,
1.插入排序, 从第二个数开始,先将第二个数做一个副本放在一旁(变量中)。
2.第二个数同前一个数比较,小于则用前一个数覆盖第二个数, 然后将副本放在前一个数前面
3.再将第三个数做一个副本取出,第三个数同前一个数比较,小于则用前一个数覆盖第三个数(此时第二个数位置空闲), 然后用副本同前一个数的前一个数比较,如果小于,则用前一个数的前一个数覆盖在原本的第二个位置上(此时第一个位置空闲), 将副本放入即可。
4.将数组中接下来的数依次做与3类似步骤,以3类推将副本往前作比较。直到副本不小于比较的数则该轮插入结束
5.重复4步骤,直到最后一个数
现在就用C实现一次
#include <stdio.h>
int main(void) {
int a[10] = {5,1,2,4,9,8,7,6,3,0};
int i, j, k;
for(i = 1; i < 10; i++) {
for(j = i; j > 0; j--) {
int data;
if(a[j-1] > a[j]) {
data = a[j];
a[j] = a[j-1];
a[j-1] = data;
}
}
}
for(k = 0; k < 10; k++)
printf("%d ", a[k]);
printf("\n");
return 0;
}
还有一种插入排序的写法, 将判断条件都写在for中
#include <stdio.h>
int main(void) {
int a[10] = {5,1,2,4,9,8,7,6,3,0};
int i, j, k;
for(i = 1; i < 10; i++) {
var = a[i];
for(j = i; j > 0 && var < a[j -1]; j--) { /*此写法重点在此处*/
a[j] = a[j - 1];
a[j - 1] = var;
}
}
for(k = 0; k < 10; k++)
printf("%d ", a[k]);
printf("\n");
return 0;
}
-
折半插入排序算法(折半排序算法)
2020-03-19 08:54:53上一节介绍了直接插入排序算法的理论实现和具体的代码实现,如果你善于思考就会发现该算法在查找插入位置时,采用的是顺序查找的方式,而在查找表中数据本身有序的前提下,可以使用折半查找来代替顺序查找,这种排序...上一节介绍了直接插入排序算法的理论实现和具体的代码实现,如果你善于思考就会发现该算法在查找插入位置时,采用的是顺序查找的方式,而在查找表中数据本身有序的前提下,可以使用折半查找来代替顺序查找,这种排序的算法就是折半插入排序算法。
该算法的具体代码实现为:#include <stdio.h> void print(int a[], int n ,int i){ printf("%d:",i); for(int j=0; j<8; j++){ printf("%d",a[j]); } printf("\n"); } void BInsertSort(int a[],int size){ int i,j,low = 0,high = 0,mid; int temp = 0; for (i=1; i<size; i++) { low=0; high=i-1; temp=a[i]; //采用折半查找法判断插入位置,最终变量 low 表示插入位置 while (low<=high) { mid=(low+high)/2; if (a[mid]>temp) { high=mid-1; }else{ low=mid+1; } } //有序表中插入位置后的元素统一后移 for (j=i; j>low; j--) { a[j]=a[j-1]; } a[low]=temp;//插入元素 print(a, 8, i); } } int main(){ int a[8] = {3,1,7,5,2,4,9,6}; BInsertSort(a, 8); return 0; }
运行结果为:
1:13752496
2:13752496
3:13572496
4:12357496
5:12345796
6:12345796
7:12345679折半插入排序算法相比较于直接插入排序算法,只是减少了关键字间的比较次数,而记录的移动次数没有进行优化,所以该算法的时间复杂度仍是
O(
。)
-
排序算法 | 插入排序算法原理及实现和优化
2018-10-23 10:01:12插入排序算法是所有排序方法中最简单的一种算法,其主要的实现思想是将数据按照一定的顺序一个一个的插入到有序的表中,最终得到的序列就是已经排序好的数据。 直接插入排序是插入排序算法中的一种,采用的方法是:...插入排序算法
是所有排序方法中最简单的一种算法,其主要的实现思想是将数据按照一定的顺序一个一个的插入到有序的表中,最终得到的序列就是已经排序好的数据。直接插入排序
是插入排序算法中的一种,采用的方法是:在添加新的记录时,使用顺序查找的方式找到其要插入的位置,然后将新记录插入。很多初学者所说的插入排序,实际上指的就是
直接插入排序算法
,插入排序算法还包括折半插入排序
、2-路插入排序
,表插入排序
和希尔排序
等,后序文章都会一一讲到。所以要完成插入排序,就需要找到这个待插入元素的位置。下面我们一起看看插入排序的具体操作原理。
插入排序的原理
插入排序实际上把待排序的数列分为了两部分,一部分已排好序,另一部分待排序。我们下面还是以一组实际数据为例进行讲解。例如采用直接插入排序算法将无序表{3,1,7,5,2,4,9,6}进行升序排序的过程为:
- 首先考虑记录 3 ,由于插入排序刚开始,有序表中没有任何记录,所以 3 可以直接添加到有序表中,则有序表和无序表可以如图所示:
- 向有序表中插入记录 1 时,同有序表中记录 3 进行比较,1<3,所以插入到记录 3 的左侧,如图所示:
- 向有序表插入记录 7 时,同有序表中记录 3 进行比较,3<7,所以插入到记录 3 的右侧,如图所示:
- 向有序表中插入记录 5 时,同有序表中记录 7 进行比较,5<7,同时 5>3,所以插入到 3 和 7 中间,如图所示:
- 向有序表插入记录 2 时,同有序表中记录 7进行比较,2<7,再同 5,3,1分别进行比较,最终确定 2 位于 1 和 3 中间,如图所示:
- 照此规律,依次将无序表中的记录 4,9 和 6插入到有序表中,如图所示:
接下来我们总结一下直接插入排序的整个执行过程:
- 首先需要明确待排序的数列由两部分组成,一部分是已排好序的部分,另一部分是待排序的部分;
- 接着我们每次选择待排序的部分的第 1 个元素,分别与前面的元素进行比较。当大于前面的元素时,可以直接进入已排好序的部分;当小于前面的元素时,需要把这个元素拿出来,将前面的元素后移一位,继续与前面的元素相比,直到比较完数组的第 1 个元素或者出现一个元素小于我们拿出来的这个元素,这时停止比较、移动,直接把这个元素放到当时的空位上;
- 一直重复步骤 2,当待排序的部分已经没有元素可进行插入时,停止操作,当前的数列为已排好序的数列。
插入排序的实现
插入排序的实现代码已经可以写出来了。首先外层肯定有个大循环,循环这个待排序的部分的数列,内层是分别与前 1 个元素进行比较、移动,直到找到位置进行插入为止。
下面我们看看插入排序的代码实现。
public class InsertSort { public static void main(String[] args) { int[] array = {5, 9, 1, 9, 5, 3, 7, 6, 1}; // 待排序数组 sort(array); print(array); } /** 从小到大 */ public static void sort(int array[]) { int length = array.length; // 循环待排序的部分的数列 // 第一个数据(下标为0的数据)由于插入排序刚开始,有序表中没有任何记录,可以直接添加到有序表中 for (int i = 1; i < length; i++) { int temp = array[i]; int j = i; // 如果前面的元素小于temp,则向后移 for (; j > 0 && array[j - 1] > temp; j--) { array[j] = array[j - 1]; } // 前一个元素(array[j - 1])和后一个元素(array[j])是相同的 // 在下一轮时,当array[j - 1]小于或等于temp时,将temp插入array[j](即上一轮的array[j - 1]) array[j] = temp; } } /** * 打印数组 */ public static void print(int array[]) { for (int i = 0; i < array.length; i++) { System.out.print(array[i] + " "); } System.out.println(); } }
插入排序的特点及性能
插入排序的操作很简单,而且我们通过上面的实例及原理可以知道,插入排序在数列近似有序时,效率会比较高,因为这样会减少比较和移动的次数。
插入排序的时间复杂度是 O(n2),我们会发现这个实现是个双重嵌套循环,外层执行n遍,内层在最坏的情况下执行 n 遍,而且除了比较操作还有移动操作。最好的情况是数列近似有序,这时一部分内层循环只需要比较及移动较少的次数即可完成排序。如果数列本身已经排好序,那么插入排序也可以达到线性时间复杂度及 O(n),所以我们应该明确地认识到,使用插入排序算法进行排序时,数列越近似有序,性能就越高。
插入排序的空间复杂度是 O(1),是常量级的,由于在采用插入排序时,我们只需要使用一个额外的空间来存储这个“拿出来”的元素,所以插入排序只需要额外的一个空间去做排序,这是常量级的空间消耗。
插入排序是稳定的,由于是数组内部自己排序,把后面的部分按前后顺序一点点地比较、移动,可以保持相对顺序不变,所以
插入排序是稳定的排序算法
。插入排序的适用场景
插入排序的性能并不是很好,和冒泡排序也算是“难兄难弟”了。但插入排序也有一个好处就是所占用的空间很少,只有一个存储临时变量的额外空间就够了。
插入排序由于其时间复杂度并不是很好,所以很少会被单独使用。在所有的基本排序算法中,在一般情况下我们可以直接选择快速排序,因为这个排序算法已经够用了。
由于在数列近似有序时,性能会比较好,而且对于元素较少的情况,时间复杂度就算是 O(n2) 也不会消耗太多的性能,所以插入排序并非一无是处。
前面提到,在快速排序的分区规模达到一定的值比如 10 时,我们会改用插入排序算法去排序那个分区的数据。而快速排序的最后的数据往往是近似有序的,所以使用快速排序的性能并不一定会有多好,这时使用插入排序的实际性能往往会更好些。所以很多编程语言在内部对快速排序的实现也是在分区的元素数量达到了一定小的规模时,改用插入排序对分区的数据元素进行排序操作。
插入排序的优化
下面的优化就不写代码了,感兴趣的可以自己百度一下。
- 折半插入排序算法(折半排序算法)
前面介绍了直接插入排序算法的理论实现和具体的代码实现,如果你善于思考就会发现该算法在查找插入位置时,采用的是顺序查找的方式,而在查找表中数据本身有序的前提下,可以使用折半查找来代替顺序查找,这种排序的算法就是折半插入排序算法。
折半插入排序算法相比较于直接插入排序算法,只是减少了关键字间的比较次数,而记录的移动次数没有进行优化,所以该算法的时间复杂度仍是 O(n2)。
- 2-路插入排序算法
2-路插入排序算法是在折半插入排序的基础上对其进行改进,减少其在排序过程中移动记录的次数从而提高效率。
具体
实现思路
为:另外设置一个同存储记录的数组大小相同的数组 d,将无序表中第一个记录添加进 d[0] 的位置上,然后从无序表中第二个记录开始,同 d[0] 作比较:如果该值比 d[0] 大,则添加到其右侧;反之添加到其左侧。在这里的数组 d 可以理解成一个环状数组。
2-路插入排序相比于折半插入排序,只是减少了移动记录的次数,没有根本上避免,所以其时间复杂度仍为O(n2)。
- 表插入排序算法
前面所介绍到的三种插入排序算法,其基本结构都采用数组的形式进行存储,因而无法避免排序过程中产生的数据移动的问题。如果想要从根本上解决只能改变数据的存储结构,改用链表存储。
表插入排序,即使用链表的存储结构对数据进行插入排序。在对记录按照其关键字进行排序的过程中,不需要移动记录的存储位置,只需要更改结点间指针的指向。
与直接插入排序相比只是避免了移动记录的过程(修改各记录结点中的指针域即可),而插入过程中同其它关键字的比较次数并没有改变,所以表插入排序算法的时间复杂度仍是O(n2)。
- 首先考虑记录 3 ,由于插入排序刚开始,有序表中没有任何记录,所以 3 可以直接添加到有序表中,则有序表和无序表可以如图所示:
-
一文搞定插入排序算法
2020-06-07 00:01:06一文搞定插入排序算法 -
插入排序算法之折半插入排序算法
2018-04-19 11:34:24在百度百科开了折半排序算法的原理后,自己试着根据原理写出了版本一的算法,版本二是参照巨人的实现思想,版本二才是重点。版本一可以忽略不看。算法同样的目的是寻找正确的插入点。版本一:实现思想:第一步:获取... -
插入排序算法实现
2018-04-28 00:08:13插入排序算法实现输入第一行是待排序数据元素的个数; 第二行是待排序的数据元素。输出一趟直接插入排序算法结果。样例输入10 50 36 41 19 23 4 20 18 12 22 样例输出36 50 41 19 23 4 20 18 12 22首先先来理解下... -
插入排序算法--直接插入算法,折半排序算法,希尔排序算法(C#实现)
2013-08-16 21:44:37插入排序算法主要分为:直接插入算法,折半排序算法(二分插入算法),希尔排序算法,后两种是直接插入算法的改良。因此直接插入算法是基础,这里先进行直接插入算法的分析与编码。 直接插入算法的排序思想:假设... -
C++实现插入排序算法(直接插入排序、折半插入排序、希尔排序)
2020-11-01 13:53:47排序算法分为五大类,一共是有九种,如下: 插入类:直接插入排序、折半插入排序、希尔排序 交换类:冒泡排序、快速排序 选择类:简单选择排序、堆排序 归并类:二路归并排序 基数类:多关键字排序 九种算法的时间... -
Python插入排序算法
2019-04-08 18:08:28插入排序算法,简单直观的排序算法.工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入. Python代码如下: # coding:utf-8 import random class Insert: ... -
快速排序算法与插入排序算法的结合
2015-09-02 17:22:25在这一篇中笔者要讲的是插入排序算法与快速排序算法的结合,为什么要这样结合使用?因为插入排序对基本排好序的数组来做排序的速度很快,而快速排序能将无序数组快速的变化为基本有序,那大家可能就问,就使用快排就... -
简单插入排序算法
2019-06-27 15:31:18简单插入排序算法 时间复杂度:O(N^2) 原理:每一趟将带排序中的元素,按其关键字大小,插入到已排序的表中的适合的位置,直到所有待排序元素全部插入为止。插入排序每次排序完成,从而得到一个新的、记录数量增1... -
算法学习笔记之直接插入排序算法
2019-07-01 06:56:16算法学习笔记之直接插入排序算法 直接插入排序算法原理 从第一个元素开始,该元素可以认为已经被排序 取出下一个元素,在已经排序的元素序列中从后向前扫描 如果该元素(已排序)大于新元素,将该元素移到下一位置 ... -
排序算法:直接插入排序算法实现及分析
2018-02-22 19:22:08直接插入排序算法介绍还是先过一遍定义。直接插入排序(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。来我们用通俗一点的话说,就是把数组中... -
经典排序算法(4)——折半插入排序算法详解
2016-03-16 13:12:51折半插入排序(Binary Insertion Sort)是一种插入排序算法,通过不断地将数据元素插入到合适的位置进行排序,在寻找插入点时采用了折半查找。 一、算法基本思想 (1)基本思想 折半插入排序的基本思想是:... -
实现直接插入排序算法
2019-02-14 10:43:21* 实现直接插入排序算法 * 实验目的: * 领会直接插入排序的过程和算法设计 * 实验内容: * 设计程序,实现直接插入排序算法。用相关数据进行测试,并 * 输出各趟的排序结果。 */ #include <stdio.h> ... -
(排序算法)linux c语言实现二分插入排序算法(简化版本的插入排序算法)
2018-11-02 12:26:01二分插入算法是在已经排序好的序列里插入一个元素,是稳定的算法,关键词是折中。 比如说我要在12345678910里插入一个3,那么我先看看中间的数比3大,还是比3小,要是比3大,我就去后一半,如果是比3小,我就去前... -
实现折半插入排序算法
2019-02-14 11:29:54* 实现折半插入排序算法 * 实验目的: * 领会折半插入排序的过程和算法设计 * 实验内容: * 设计程序,实现折半插入排序算法。用相关数据进行测试,并 * 输出各趟的排序结果。 */ #include <stdio.h> ...