数据结构与算法--希尔排序

本文详细介绍了希尔排序的起源,其基于插入排序的改进思想,探讨了增量序列的选择策略,如原始希尔排序、Hibbard增量序列和Sedgewick增量序列,以及它们对性能的影响。通过代码实例演示了如何实现希尔排序的不同版本。
摘要由CSDN通过智能技术生成

希尔排序的由来

利用插入排序和冒牌排序消除逆序对的思想,插入排序和冒泡排序一次交换或移动只能消除一个逆序对儿,希尔排序进行了改进,一次交换消除多个逆序对(排序的本质就是消除逆序对)

希尔排序算法思想

1.定义增量序列Dm>Dm-1>…>D1=1
2.对每个Dk进行“Dk-间隔”排序(k= m,m-1…1)
注意: “Dk间隔”有序的序列,在执行“Dk-1间隔”排序后,仍然是“Dk间隔”有序的

增量的选择

原始希尔排序

每次对增量序列进行二分

最坏情况 :T=O(n*n)

举个坏例子,改序列每次增量都满足大小要求,8、4、2均不改变序列,最后还是只能靠1增量,降为插入排序

当增量元素不互质,则小增量可能根本不起作用

Hibbard增量序列
Dk=2^k - 1 --相邻元素互质
最坏情况: T=O(N^3/2)
猜想:Tavg=O(N^5/4) (未得到证明)

Sedgewick增量序列
{1,5,19,41,109…}
——94^i - 92^i +1 或 4^i -3*2^i +1
猜想:Tavg=O(N^7/6) ,
Tworst=O(N^4/3)
当数据量为几万,希尔排序结合Sedgewick增量序列效果就很好

代码实现

希尔排序是基于插入排序的思想,所以代码跟插入排序很相似,只需要将原始的1改为每次的增量序列即可

原始插入排序代码(增量均为1):

void Insertion_sort(ElementType A[],int n)
{
	for(int i=1;i<n;i++) 
	{
		ElementType tmp=A[i];
		int j=i;
		for(;j>=1&&A[j-1]>tmp;j--)
		{
			A[j]=A[j-1];     
		}
		A[j]=tmp;      
	}
}

原始增量序列希尔排序代码:
在这里插入图片描述

void Shell_sort(ElementType A[],int n)
{
	for(int d=n/2;d>0;d/=2)    //希尔增量序列 
	{
		for(int i=d;i<n;i++)   
		{
			ElementType tmp=A[i];
			int j=i;
			for(;j>=d&&A[j-d]>tmp;j-=d)
			{
				A[j]=A[j-d];      
			}
			A[j]=tmp;        
		}
	}
	
} 

Sedgewick增量序列

void Shell_sort_Sed(ElementType A[],int n)
{
	int Si;
	int Sedgewick[]={929,505,209,109,41,19,5,1,0};
	//初始的增量Sedgewick[Si]不能超过待排序列长度,即 找到小于n的最大增量 
	for(Si=0;Sedgewick[Si]>=n;Si++);
	
	for(int d=Sedgewick[Si];d>0;d=Sedgewick[++Si])    //希尔增量序列 
	{
		for(int i=d;i<n;i++)   
		{
			ElementType tmp=A[i];
			int j=i;
			for(;j>=d&&A[j-d]>tmp;j-=d)
			{
				A[j]=A[j-d];      
			}
			A[j]=tmp;        
		}
	}
	
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值