赞
踩
在写插入排序的代码之前,我们先对插入排序的排序原理进行梳理:
插入排序一共分为三种,分别是:直接插入排序、分别插入排序、希尔排序
在严蔚敏的《数据结构(C语言版)》中对直接插入排序是这样定义的:
直接插入排序(Selection Insertion Sort)是一种最简单的排序方法,它的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的记录新增1的有序表。
如下图,我在这里给出了一组数据:
int ar[] = {1,2,3,7,6,5,4};
我们在画板对这组数据利用插入排序法进行排序,并将每一趟的排序结果都写出来:
在这里我画出了上面给出的数组以及元素的下标。当i和j分别指向3号下标和4号下标时满足代码(if(ar[i] < ar[i - 1])),这时i下标指向的6 小于i - 1指向的 7 使函数继续往下执行,这时将7付给临时变量temp;
现在开启第二层for循环,此时原本的i - 1下标相当于第二层for循环里面的j下标,这时从j下标的位置从后向前扫描,只要前面的序列里面还有比j下标指向的元素更小的元素,就把前面的序列的每一个元素全部向后移动一个位置,这句话对应代码语句中的(ar[j + 1] = ar[j]),并且因为3<6<7,我们应该把6插入到3和7的中间位置,并且应该把三号下标对应的7元素向后移动一个位置。
我们这时开始执行插入存放ar[i]的temp,此时对应代码语句中的(ar[j + 1] = temp;)到这时我们再回到图中:
这就是插入排序的第五趟操作(因为前四次都是满足后面大于前面的规则的)。
此时,我们在执行第六趟操作时依旧依照上面的思路进行执行,当我们的i下标指向5号下标对应的5元素时,发现并不满足前面小于后面元素的规则,这时开始执行第二层for循环,将5和前面已经排序好的1,2,3,6,7这五个元素进行比较,最后发现 6>5>3 ,所以这时,我们将5赋值给temp临时值,将6和7元素统一向后迁移一位,再将存放5元素的temp赋值给此时3号下标对应的地方(这就是插入操作),至此,第六趟排序结束,继续执行第三趟排序也是此过程,直到排序全部完成:
插入排序的排序原理基本清晰,我们将思路代码化:
- void Insert_sort(int *ar,int len)//插入排序默认步长为1,使用于小量级序列
- {
- int temp = 0;
- int i = 0,j = 0;
- for(i = 1;i < len;i++){//第一个循环,插入排序是从第二个元素开始排序的,所以此处的i = 1
- if(ar[i] < ar[i - 1]){//限定条件:后面的元素小于前面的元素
- temp = ar[i];//利用临时变量保存后面的元素
- for(j = i - 1;j >= 0 && ar[j] > temp;j--){//这层循环是为了检查前面已经排序好的元素,循环执行的条件就是j下标不会低于0下标且前面已经排序好的元素出现了比临时变量更大的元素。
- ar[j + 1] = ar[j];//将前面已经排序好的元素统一向后迁移一位
- }
- ar[j + 1] = temp;//将temp中存放的值赋值给需要插入的位置上
- }
- }
- }
在这里我设置数组中的十个元素是计算机随机生成的小于20的数,我在第一个for循环后面添加了一个句子,要求函数每进行一次排序就进行一次序列的输出,我们看一下计算机进行的每趟排序与我们分析的是不是一样的:
如图,计算机生成的原始数据为:
{7,8,16,8,15,18,3,19,8,12};
显然,序列前面的3个元素都是满足后面大于前面的规则的,直到第四个元素,8 < 16这时已不满足规则,向下执行for循环,我们是从第一个元素开始比较的,所以是遍历两次,且前两次遍历序列的顺序是一样的。
我们看运行结果,前两次的结果确实是一样的。
此时因为16>8>=8所以应该把8元素插入在8和16之间,如图第三趟是符合我们的推理的。
依此类推,插入排序最终的结果为:
{3,7,8,8,8,12,15,16,18,19};
分析完成。
接下来我们对系统随机分布的10个小于20的整数进行排序,看看结果正不正确:
- #include<stdio.h>
- #include<iostream>
- #include<stdlib.h>
- #include<assert.h>
- #include<time.h>
- #define MAXSIZE 10
- void initar(int *ar,int len)
- {
- assert(ar != nullptr);
- for(int i = 0;i < len;i++){
- ar[i] = rand() % 20;
- }
- }
- void showar(int *ar,int len)
- {
- assert(ar != nullptr);
- for(int i = 0;i < len;i++){
- printf("%d ",ar[i]);
- }
- printf("\n--------------------------\n");
- }
- void Insert_sort(int *ar,int len)//插入排序默认步长为1,使用于小量级序列
- {
- assert(ar != nullptr && len >= 0);
- int temp = 0;
- int i = 0,j = 0;
- for(i = 1;i < len;i++){//第一个循环,插入排序是从第二个元素开始排序的,所以此处的i = 1
- if(ar[i] < ar[i - 1]){//限定条件:后面的元素小于前面的元素
- temp = ar[i];//利用临时变量保存后面的元素
- for(j = i - 1;j >= 0 && ar[j] > temp;j--){//这层循环是为了检查前面已经排序好的元素,循环执行的条件就是j下标不会低于0下标且前面已经排序好的元素出现了比临时变量更大的元素。
- ar[j + 1] = ar[j];//将前面已经排序好的元素统一向后迁移一位
- }
- ar[j + 1] = temp;//将temp中存放的值赋值给需要插入的位置上
- }
- }
- }
- int main()
- {
- srand((unsigned int)time(NULL));
- int ar[MAXSIZE];
- initar(ar,MAXSIZE);
- printf("原始数据为:\n");
- showar(ar,MAXSIZE);
- printf("\n\n经过插入排序后的数据为:\n");
- Insert_sort(ar,MAXSIZE);
- showar(ar,MAXSIZE);
- return 0;
- }
运行结果为:
如图,成功的将系统随机生成的10个小于20的整数进行了从小到大的排序。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。