常见排序算法总结(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;
}
}
}
}
标签:int,插入排序,len,gap,希尔,C++,排序 来源: https://blog.csdn.net/weixin_44572229/article/details/119083610
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。