数据结构(希尔排序)

希尔排序

希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,因D.L.Shell于1959年提出而得名
之前我们已经讲过直接插入排序
直接插入排序:https://blog.csdn.net/wfea_lff/article/details/104002438
这里就不多说了,直接进入主题

时间复杂度: O(n^1.3 ~ n^1.5)

空间复杂度 : O(1)

稳定性: 不稳定

希尔排序最关键的地方就在于分组,他就是因为分组的合理,使得算法的优化
排序过程如图所示:

在这里插入图片描述
从图中我们不难看出
相当于对直接插入排序的优化
1、先对数据进行分组,然后在同一组内使用直接插入将数据排序,其目的就是使得整个数据趋于有序
每次分组排序,从分好的第一组的第二个数据开始,按直接插入排序使得
第一组的前两个数据有序,
第二组的前两个数据有序,
。。。
第一组的前三个数据有序
。。。
2、分组的个数依次减少,做相同的事情 --》 第一次 5组 第二次 3组 第三次 1组

分组的序列: 序列中的任何两个元素都是互质的, 并且最后一个分组必须为1

分组的目的

使得待排序数字集变得较为有序,对于直接插入排序而言,数据越有序,其时间复杂度将越趋于O(n)

我这里用个例子来详细说明

例如:5,4,6,9,2,8,7

第一次排序
我们先将整个待排序的数字集先分组,我们首先分三组
第一组【5,9,7】
第二组【4,2】
第三组【6,8】
注意:这里只是我们算法思想上分的,不是真的用三个数组来分出来
我们不难看出分组的规律,第一个数字和第四个数字和第七个数字,即就是该数字的序号+3(这里我是+3处理的,可根据情况自己定,这里只是举例)
定义i为第一组第二个数字9的下标,让其与同组的前一个数字5相比较,和直接插入排序相同,如果比前一个数字大则i++,变成了第二组第二个数字2,在与该组的前一个数字4比较,比前一个数字小,则将该组第一个数字4,放到2的位置,把2放到4的位置;这个时候因为该组2之前已经没有数字了,所以继续i++,变成了第三组的第二个数字8,继续上述的操作,就完成了第一次排序
排序结果:5,2,6,7,4,8,9

第二次排序
我们这次分一组(无论怎么划分组,最后分的一组都是一个数字是一组)
最后一次排序相当于直接插入排序,这个时候因为待排序的数字集已经变得较为有序,所以算法的排序性能越好,这里对直接插入排序就不多说了
排序结果:2,4,5,6,7,8,9

参考代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define LENGTH 15        //待排序的数字个数

void Shell(int arr[],int len,int width)       //一次分组排序
{
	int i,j,tmp;
	for(i=width;i<len;i++)
	{
		tmp = arr[i];
		for(j=i-width;j>=0;j-=width)
		{
			if(arr[j]<=tmp)
			{
				break;
			}
				arr[j+width] = arr[j];
		}
		arr[j+width] = tmp;
	}
}

void ShellSort(int arr[],int len)        //希尔排序
{
	for(int i=9;i>=1;i/=2)
	{
		Shell(arr,len,i);
	}
}

void ShowSort(int arr[],int len)     //打印
{
	for(int i=0;i<len;i++)
	{
		printf("%2d  ",arr[i]);
	}
	printf("\n");
}

int main()
{
	srand((unsigned int)time(NULL));

	int arr[LENGTH];

	for(int i=0;i<LENGTH;i++)
	{
		arr[i] = rand()%100;   //获得随机数
	}
	ShowSort(arr,LENGTH);       //打印

	ShellSort(arr,LENGTH);    //希尔排序

	ShowSort(arr,LENGTH);
	return 0;
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值