算法 - C语言实现插入排序(Insert_sort)

在写插入排序的代码之前,我们先对插入排序的排序原理进行梳理:

插入排序一共分为三种,分别是:直接插入排序、分别插入排序、希尔排序

在严蔚敏的《数据结构(C语言版)》中对直接插入排序是这样定义的:

直接插入排序(Selection Insertion Sort)是一种最简单的排序方法,它的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的记录新增1的有序表。

如下图,我在这里给出了一组数据:

int ar[] = {1,2,3,7,6,5,4};

我们在画板对这组数据利用插入排序法进行排序,并将每一趟的排序结果都写出来:

算法 - C语言实现插入排序(Insert_sort)_第1张图片

在这里我画出了上面给出的数组以及元素的下标。当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;)到这时我们再回到图中:

算法 - C语言实现插入排序(Insert_sort)_第2张图片

这就是插入排序的第五趟操作(因为前四次都是满足后面大于前面的规则的)。

此时,我们在执行第六趟操作时依旧依照上面的思路进行执行,当我们的i下标指向5号下标对应的5元素时,发现并不满足前面小于后面元素的规则,这时开始执行第二层for循环,将5和前面已经排序好的1,2,3,6,7这五个元素进行比较,最后发现 6>5>3 ,所以这时,我们将5赋值给temp临时值,将6和7元素统一向后迁移一位,再将存放5元素的temp赋值给此时3号下标对应的地方(这就是插入操作),至此,第六趟排序结束,继续执行第三趟排序也是此过程,直到排序全部完成:

算法 - C语言实现插入排序(Insert_sort)_第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
#include
#include
#include
#include
#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;
}

运行结果为:

算法 - C语言实现插入排序(Insert_sort)_第4张图片

如图,成功的将系统随机生成的10个小于20的整数进行了从小到大的排序。 

你可能感兴趣的:(算法,算法,数据结构,c语言)