常见排序算法-插入排序

一、排序的概念:

排序就是将一组杂乱无章的数据按照一定的规律(升序或降序)组织起来。

二、常见的排序算法:

目录

1.直接插入排序:

2.希尔排序

3.直接插入排序和希尔排序对比 :


三、算法实现

1.直接插入排序:

概念:直接插入排序(Straight Insertion Sort)是一种最简单的排序方法,其基本操作是将一条记录插入到已排好的有序表中,从而得到一个新的、记录数量增1的有序表。 

因为直接插入排序要求插入到已经排好的有序序列中,我们可以依次插入一个数进行排序使每次插入都实现直接插入排序最后插入一个数时序列有序。

所以我们要实现两次循环:

第一次循环将前一个数当作一个有序序列

第一次循环将前一个数当作一个有序序列

......

......

第n次循环将前n个数当作一个有序序列

升序实现代码:

void InsertSort(int* a, int n) {           //传入要排序的数组和数组大小
	assert(a);
	int end = 0;                           //end记录当前数的位置
	for (int i = 0; i < n - 1; i++) {
		end = i;
		int x = a[end + 1];                //x为下一个要排序的数
		while (end >= 0) {                 //进行单次的排序
			if (x < a[end]) {
				a[end + 1] = a[end];
				end--;
			}
			else {
				break;
			}
		}
		a[end + 1] = x;
	}
}

我们用一个测试案列看看效果:

思想: 刚开始执行时,end是数组第一个元素的下标,x存放的是end后面一个元素的值,让数组的end下标对应的值与x的值进行比较。若为升序,end下标对应的值如果大于x中存放的值就交换,然后让end--,然后while循环让end下标对应的值与tmp比较,若end<0就跳出,若end对应下标的值小于x要break(避免不必要的比较),跳出内循环后让end+1下标对应数组元素等于x。然后使end指向第二个元素的下标,同样的方法依次比较。

时间复杂度:O(n^2)

空间复杂度:O(1)

2.希尔排序

概念:希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”,是直接插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。

因为我们发现直接插入排序在最坏情况下时间复杂度为O(n^2),所以我们想将一个序列成为接近有序序列,那么排序时间就会大幅降低。

所以希尔排序分为两个部分: 预排序和直接插入排序

预排序将数组间隔gap为一组,对每一组进行直接插入排序,那么整个序列就会接近有序

而当我们不断减小gap大小直到gap等于1那么相当于进行直接插入排序整个序列有序

而gap为组间距,gap越大预排序越快,gap越小组内约接近有序。

升序代码实现:

void ShellSort(int* a, int n) {
	int gap = n;
	while (gap > 1) {
		gap=gap/ 2;
		for (int i = 0; i < n - gap; ++i) {
			int end = i;
			int x = a[end + gap];
			while (end >= 0) {
				if (x < a[end]) {
					a[end + gap] = a[end];
					end -= gap;
				}
				else {
					break;
				}
			}
			a[end + gap] = x;
		}
	}
}

一样我们写个测试案例:

思想:我们让不断的让gap等于n/2让数组快速的靠近有序直到gap等于1数组有序。

3.直接插入排序和希尔排序对比 :

在序列很小时我们很难看出希尔排序对于直接插入排序的优化我们写一个较大的序列来记录他们运行的时间来看看他们的差别

void testop() {
	srand(time(0));
	const int N = 10000;
	int* a1 = (int*)malloc(sizeof(int) * N);
	int* a2 = (int*)malloc(sizeof(int) * N);
	for (int i = 0; i < N - 1; i++) {
		a1[i] = rand();
		a2[i] = a1[i];

	}
	int begin1 = clock();
	InsertSort(a1, N);
	int end1 = clock();

	int begin2 = clock();
	ShellSort(a2, N);
	int end2 = clock();
	printf("%d\n", end1 - begin1);
	printf("%d\n", end2 - begin2);
	free(a1);
	free(a2);
}

我们开辟一个10000大小的数组用srand函数来随机生成一些随机数存入数组,用两种排序方法对其排序,用clock函数记录他们的运行时间来直观看看他们的差别。

运行结果如下:

我们发现在有10000个数的时候直接插入排序时间约为希尔排序的百倍级别而当数据越多他们的差距越大,所以希尔排序大大优化了直接插入排序。 


 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一叶丨之秋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值