[希尔排序算法](C语言版)

排序算法多种多样。今天介绍一种新的排序算法,希尔排序算法。

希尔排序(Shell Sort),是插入排序的一种改进版本。由唐纳得希尔教授(Donald Shell)于1959年提出,故得名。

希尔排序的基本思想是:将待排序列分割成若干子序列分别进行插入排序,具体分割的方式是由一个增量序列gap决定的,而这个gap由原数据的长度,每次折半得到(gap=length/2),直到2,1.。当gap=1时,整个序列作为一个整体对待,变成了普通的插入排序。

希尔排序算法的排序过程如下:

本例中,原始数据有20个数:36,28,78,69,55,45,99,12,7,8,5,21,27,33,81,88,66,10,19,26。假设按升序排序。则:

第一轮gap=20/2=10,即表示将原数据分成10组,每组两个,两者的指针相差gap(10),分别排序。

分组情况如下(注:此分组仅为虚拟分组,不移动各组数据的物理位置,以下同):

【36,5】、【28,21】、【78,27】、【69,33】、【55,81】、【45,88】、【99,66】、【12,10】、【7,19】、【8,26】

各组排序结果如下:

【5,36】、【21,28】、【27,78】、【33,69】、【55,81】、【45,88】、【66,99】、【10,12】、【7,19】、【8,26】

第一轮得到结果如下:

5,21,27,33,55,45,66,10,7,8,36,28,78,69,81,88,99,12,19,26

第二轮10/2=5,即上一步得到的数据分成5组,每组4个数,组内两数位置相差 gap=5,分组情况为:

【5,45,36,88】、【21,66,28,99】、【27,10,78,12】、【33,7,69,19】、【55,8,81,26】

各组排序结果如下:

【5,36,45,88】、【21,28,66,99】、【10,12,27,78】、【7,19,33,69】、【8,26,55,81】

第二轮排序结果为:

5,21,10,7,8,36,28,12,19,26,45,66,27,33,55,88,99,78,69,81

第三轮5/2,再将上一步得到的数据分成2组,每组10个数。分组情况为:

【5,10,8,28,19,45,27,55,99,69】、【21,7,36,12,26,66,33,88,78,81】

各组排序结果如下:

【5,8,10,19,27,28,45,55,69,99】、【7,12,21,26,33,36,66,78,81,88】

第三轮排序结果为:

5,7,8,12,10,21,19,26,27,33,28,36,45,66,55,78,69,81,99,88

第四轮1.,此时gap=1,将上步得到的数据当成一个整体看待,运用一遍插入排序即可得到最终结果。

5,7,8,10,12,19,21,26,27,28,33,36,45,55,66,69,78,81,88,99

本算法在DEV  c++5.11平台验证通过。

/*
****************************************************************************
对数组内的一组数据进行升序/降序排序,采用希尔排序算法。 
****************************************************************************
*/

#include <stdio.h>



//定义并实现希尔排序函数 ,传入三个参数,一个数据指针,一个数据大小,一个排序升降序标志 
void ShellSort(int *num,int len,int order){
	int i,j,temp,gap;
	gap=len;
	
	while (gap>1){
		gap /= 2;//分组的间隔数,每间隔gap的数分成一组,len/2,len/4,len/8...2,1(折半分组) 
		
		for (i=gap;i<len;i++){//i指针从gap开始,至数组尾 ,每次加1,依次遍历 
			temp = num[i];//temp暂存i指针指向的数据,与j指针指向的数据进行比较 
			for(j=i-gap;j>=0;j-=gap)//j指针比i指针相差gap,每次递减gap 
			{
				if (order!=0){
    				if (temp > num[j])
    				{
    					num[j + gap] = num[j];
    				}
    				else
    				{
    					break;
    				}
				}
				else{
    				if (temp < num[j])
     				{
     					num[j + gap] = num[j];
    				} 
    				else               
    				{
    					break;
    				}					
				}
				
			}
			num[j+gap] = temp;
		}
	}
}



int main() {
	int i, j, temp;
	int num[] = {36,28,78,69,55,45,99,12,7,8,5,21,27,33,81,88,66,10,19,26};
	int len=sizeof(num)/sizeof(int);
	int *p=num;
	int order=0;

	printf("数组中有%d个元素。它们分别是:\n",len);
	for (i=0; i<len; i++) {
		printf("%d,",num[i]);
	}
	printf("\n");

    printf("请输入排序方式(0:升序,非0数字:降序):");
    scanf("%d",&order);
    
      
	ShellSort(p,len,order);
	     
    if (order != 0 ){
	    printf("\n降序排序结果如下:\n");
        	for (i=0; i<len; i++) {
	        	printf("%d,",*p++);
	        }
	    printf("\n");
	}else{
		printf("\n升序排序结果如下:\n");
	    for (i=0; i<len; i++) {
		    printf("%d,",*p++);
	    }
	    printf("\n");
	}
	
	
	return 0;


}

程序运行结果如下,完美实现升序排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值