C/C++排序算法(2)希尔排序

2021/7/25 17:06:17

本文主要是介绍C/C++排序算法(2)希尔排序,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

常见排序算法总结(2)希尔排序

一篇文章,带你搞懂 希尔排序 (注:代码语言的选择不应该限制了我们对算法的理解)

文章附有动图!一看就懂!

 

(1)工作原理 希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序 是非稳定排序算法。 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。 希尔排序是基于插入排序的以下两点性质而提出改进方法的: ①插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。 ②但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位。 希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接 插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。 (2)算法步骤 ①选择一个增量序列 t1,t2,…,tk,其中 ti>tj,tk=1; ②按增量序列个数 k,对序列进行 k 趟排序; ③每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对 各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为 整个序列的长度。 希尔排序的示例:

 

(3)性能分析 ①希尔排序的时间复杂度与增量(即,步长 gap)的选取有关。例如,当增量为 1 时,希 尔排序退化成了直接插入排序,此时的时间复杂度为 O(N²),而 Hibbard 增量的希尔排序的 时间复杂度为 O(N^ 3/2 )。 ②稳定性:不稳定

 

来看一下更直观的图

最后,我们来看一下希尔排序的动画演示,相信你会感叹道,噢原来就是这样。 

 

 代码实现:

#include <stdio.h>
#include <malloc.h>

void shellSort(int *a, int len); // 函数声明

int main(void)
{
    int i, len, * a;
    printf("请输入要排的数的个数:");
    scanf("%d",&len);
    a = (int *)malloc(len * sizeof(int)); // 动态定义数组
    printf("请输入要排的数:\n");
    for (i = 0; i < len; i++) { // 数组值的输入
        scanf("%d",&a[i]);
    }   
    shellSort(a, len); // 调用希尔排序函数
    printf("希尔升序排列后结果为:\n");
    for (i = 0; i < len; i++) { // 排序后的结果的输出
        printf("%d\t",a[i]);
    }
    printf("\n");

    return 0;
}

void shellSort(int *a, int len)
{
    int i, j, k, tmp, gap;  // gap 为步长
    for (gap = len / 2; gap > 0; gap /= 2) {  // 步长初始化为数组长度的一半,每次遍历后步长减半,
    	for (i = 0; i < gap; ++i) { // 变量 i 为每次分组的第一个元素下标 
	        for (j = i + gap; j < len; j += gap) { //对步长为gap的元素进行直插排序,当gap为1时,就是直插排序
	            tmp = a[j];  // 备份a[j]的值
	            k = j - gap;  // j初始化为i的前一个元素(与i相差gap长度)
	            while (k >= 0 && a[k] > tmp) {
	                a[k + gap] = a[k]; // 将在a[i]前且比tmp的值大的元素向后移动一位
	                k -= gap;
	            }
	            a[k + gap] = tmp; 
	        }
	    }
    }
}



这篇关于C/C++排序算法(2)希尔排序的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程