算法训练营【day8】:: 排序篇(C语言版):插入排序:分析、实现与总结

本内容是笔者结合《数据结构(C语言版)》(严蔚敏)总结所得,记录学习过程,分享知识!


目录:
1. 插入排序分析(大白话解释)
2. 插入排序实现
- - 2.1 单次插入模拟实现
- - 2.2 插入排序实现
- - 2.3 可执行完整程序代码及结果展示
3. 插入排序总结
4. 结语及相关推荐(排序汇总)


1. 插入排序分析(大白话解释)

(大白话解释示例)插入排序就好比打麻将时,你手握清一色的饼牌(万牌、条牌),当你抽到同种牌时会看牌的大小,然后将其插入到你已有的手牌,使手牌始终有序。(当然如果你打牌、麻将从不对同型牌排序就当我没说)

在这里插入图片描述

插入排序规则,即在一个待排序序列中:

  1. 始终维护一个有序序列,序列大小可以是 1(即只有一个元素);
  2. 通常该部分有序序列总在序列从左至右(起始 => 结束);
  3. 总是选择部分有序序列后的第一个值进行插入操作,假设:有序部分的最后一个元素的索引为 end则待插入元素索引为:end+1
  4. 待插入元素 arr[end+1],逆序依次向前比较,若符合插入条件则插入序列。
  5. 重复步骤,直至排序结束!

图示如下:

在这里插入图片描述


2. 插入排序实现

2.1 单次插入模拟实现

1. 明确 end 的初值!为了部分有序时,第一次进入排序可设置为:0


2. 由于排序插入过程中,我们实现的是移动覆盖!故需要暂存待排序值!


3. 注意迭代 end!对比插入向前搜索时,end 同时用于标识当前比较对象,显然根据索引非负易得循环条件!


4. 数据插入!(注意插入位置!建议手动画图理解!)

int end = 0;	// 用于标识数组中已有序序列的位置:[0,end]已有序,从 end+1 开始待排序
int temp = array[end+1];	// 暂存待排序值
while(end >= 0){
	if( temp < array[end] ){
		array[end+1] = array[end];		// 向后覆盖 / 移动操作!
		--end;							// 向前搜索
	}
	else{
		break;
	}
}
array[end+1] = temp; 					// 数据插入!

2.2 插入排序实现

实现单次插入排序操作之后,继续分析。显然每次插入完成之后,我们原有的“部分有序序列”会增大一个单位!
实际,要对所有元素进行一次插入操作,只需遍历一遍数组即可!
注意点:由于我们标识待插入元素索引的标识方式为:end+1,故需要注意越界问题!!!
【 完整代码如下: 】

void InsertSort(DataType* array, int size) {
	// 注意循环次数!与代码实现有关!
	for (int i = 0; i < size - 1; i++) {
		int end = i;							// 用于标识数组中已有序序列的位置:[0,end]已有序,从 end+1 开始待排序
		DataType temp = array[end + 1];			// 标识当前被操作对象(插入对象)

		// 单次插入过程
		while (end >= 0) {
			if (temp < array[end]) {
				array[end + 1] = array[end];
				--end;
			}
			else {
				break;
			}
		}
		array[end + 1] = temp;
	}
}

2.3 可执行完整程序代码及结果展示
#pragma
#include<stdio.h>
/* 本篇内容将实现:C 语言版顺序存储:插入排序 */
#include<stdio.h>

typedef int DataType;

/* 打印函数 */
void PrintArray1(DataType* array, int size);
void PrintArray2(DataType* array, int size); // 测试字符排序


/* 顺序存储插入排序: */
/* 参数说明:被操作数组;数组大小 */
void InsertSort(DataType* array, int size);


/* 打印函数 */
void PrintArray1(DataType* array, int size) {
	printf("array:");
	for (int i = 0; i < size; i++)
		printf("%d ", array[i]);
	printf("\n");
}

void PrintArray2(DataType* array, int size) {
	printf("array:");
	for (int i = 0; i < size; i++)
		printf("%c ", array[i]);
	printf("\n");
}

/* 顺序存储插入排序: */
/* 参数说明:被操作数组;数组大小 */
/* 时间复杂度: O(N^2)
	最优:O(N)
	最差:O(N^2)
*/
void InsertSort(DataType* array, int size) {

	for (int i = 0; i < size - 1; i++) {
		int end = i;							// 用于标识数组中已有序序列的位置:[0,end]已有序,从 end+1 开始待排序
		DataType temp = array[end + 1];			// 标识当前被操作对象(插入对象)

		// 单次插入过程
		while (end >= 0) {
			if (temp < array[end]) {
				array[end + 1] = array[end];
				--end;
			}
			else {
				break;
			}
		}
		array[end + 1] = temp;
	}
}

void test_InsertSort() {
#if 1
	printf("============================================================\n");
	printf("整型测试用例:\n");
	int a[] = { 5,3,6,44,8,2,2,64,85,16,48,46,846,4,6843,54,846,16,48,4,1,64,684,6,46 };
	int size = sizeof(a) / sizeof(int);
	PrintArray1(&a, size);
	InsertSort(&a, size);
	PrintArray1(&a, size);

#else
	printf("============================================================\n");
	printf("字符型测试用例(注:需将 typedef int DataType; 改成:typedef char DataType;才可正常):\n");
	char b[] = "qwertyuiopasdfghjklzxcvbnm";
	int size = sizeof(b) / sizeof(char);
	PrintArray2(b, size);
	InsertSort(b, size);
	PrintArray2(b, size);
#endif
}

int main() {
	test_InsertSort();
	return 0;
}

测试结果展示:

在这里插入图片描述
在这里插入图片描述


3. 插入排序总结

关于时间复杂度:O(N^2)

  1. 最优:O(N) 【待排序序列为有序】;
  2. 最差:O(N^2) 【待排序序列恰好为逆序】

关于优化:
由上可知,当原序列有序程度越高,插入排序效率越高!若能对原序列进行预排序(通过简单操作使原序列有序程度提高!)实质上希尔排序就是对插入排序有序化在插入的优化排序!

4. 结语及相关推荐(排序汇总)

排序汇总博客
排序算法代码汇总(gitee链接)
排序算法代码汇总(github链接)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NPC的白话文谈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值