欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

排序算法:希尔排序算法实现及分析

发布时间:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的这篇文章主要介绍了 排序算法:希尔排序算法实现及分析 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

希尔排序算法介绍

希尔排序是D.LShell 与1957年提出来的一种排序算法,在这之前排序算法的时间复杂度都是O(n^2),希尔排序算法是突破这个时间复杂度的第一批算法之一。我们知道直接插入排序算法(不知道的请看:排序算法:直接插入排序算法实现及分析),在某些情况下的效率是很很高的1.当我们的记录本身就是基本有序(小的关键字基本在前面,大的基本在后面)的,我们只需要少量的插入操作,就可以完成排序。2.还有就是记录数比较少时,直接插入的优势也是比较明显的。希尔排序可以说就是直接插入排序的升级版,希尔排序通过构造上面的2个条件 使排序更快的实现。希尔排序是怎样来构造这2个条件的呢这里采用跳跃分割的策略:将相距某个“增量”的记录组成一个子序列,这样才能保证子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序

希尔排序算法实现

//希尔排序 升序 //根据插入排序的原理,将原来的一个大组,采用间隔的形式分成很多小组,分别进行插入排序 //每一轮结束后 继续分成更小的组进行 插入排序,直到分成的小组长度为1,说明插入排序完毕 void ShellSort_Up(int* arr,int length) {int increase = length;int i, j, k, temp;do{increase = increase / 3 + 1;//每个小组的长度,也就是增量//每个小组的第0个元素for (i = 0; i < increase; i++){//对每个小组进行插入排序,因为是间隔的形式分组,每个小组的下一个元素为 j+=incresefor (j = i + increase; j < length; j += increase){temp = arr[j];//待插入元素for (k = j - increase; k >= 0 && temp < arr[k]; k -= increase){arr[k + increase] = arr[k];}arr[k + increase] = temp;}}} while (increase>1); }

希尔排序算法复杂度分析

希尔排序的关键并不是随便分组后各自排序,而是将相隔某个“增量”的记录组成一个字序列,实现跳跃式的移动,使得排序的效率提高。这的“增量”选取就非常关键了。我们采用的是increase/3+1的方式选取。可究竟选取一个什么样的值,最好呢?目前还是数学难题,不过科学研究表明,当增量序列为dlta[k] = 2^(t-k+1) - 1 ,0 <=k<=t<=log2(n+1)时,可以获得不错的效率,其时间复杂度为O(n^(3/2)),要好于O(n^2)

完整代码

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/timeb.h> #define MAXSIZE 10 //交换值 void Swap(int* a, int* b) {int temp = *a;*a = *b;*b = temp; } //直接插入排序 升序 void InsertSort_Up(int* arr, int length) {//假定第0个元素是有序表,从第1个元素开始往有序表中插入数据for (int i = 1; i < length; i++){int temp = arr[i];int j;for (j = i - 1; j >= 0 && arr[j] > temp; j--){arr[j + 1] = arr[j];//往前挪}arr[j + 1] = temp;}return; } //希尔排序 升序 //根据插入排序的原理,将原来的一个大组,采用间隔的形式分成很多小组,分别进行插入排序 //每一轮结束后 继续分成更小的组进行 插入排序,直到分成的小组长度为1,说明插入排序完毕 void ShellSort_Up(int* arr,int length) {int increase = length;int i, j, k, temp;do{increase = increase / 3 + 1;//每个小组的长度//每个小组的第0个元素for (i = 0; i < increase; i++){//对每个小组进行插入排序,因为是间隔的形式分组,每个小组下一个元素为 j+=incresefor (j = i + increase; j < length; j += increase){temp = arr[j];//待插入元素for (k = j - increase; k >= 0 && temp < arr[k]; k -= increase){arr[k + increase] = arr[k];}arr[k + increase] = temp;}}} while (increase>1); } //希尔排序 降序 void ShellSort_Down(int* arr, int length) {int increase = length;int i, j, k, temp;do{increase = increase / 3 + 1;//每个小组的长度//每个小组的第0个元素for (i = 0; i < increase; i++){//对每个小组进行插入排序,因为是间隔的形式分组,每个小组下一个元素为 j+=incresefor (j = i + increase; j < length; j += increase){temp = arr[j];//待插入元素for (k = j - increase; k >= 0 && temp > arr[k]; k -= increase){arr[k + increase] = arr[k];}arr[k + increase] = temp;}}} while (increase>1); }//打印数组元素 void PrintArr(int* arr, int length) {for (int i = 0; i < length; i++){printf("%d ", arr[i]);}printf("\n");return; } long GetSysTime() {struct timeb tb;ftime(&tb);return tb.time * 1000 + tb.millitm; }int main(int argc, char *argv[]) {srand((size_t)time(NULL));//设置随机种子int arr[MAXSIZE] = { 0 };int arr2[MAXSIZE] = { 0 };//给每个元素设置一个随机值for (int i = 0; i < MAXSIZE; i++){int num = rand() % MAXSIZE;arr[i] = num;arr2[i] = num;}printf("排序前:\n");PrintArr(arr, MAXSIZE);printf("希尔排序升序:\n");ShellSort_Up(arr, MAXSIZE);PrintArr(arr, MAXSIZE);printf("希尔排序降序:\n");ShellSort_Down(arr, MAXSIZE);PrintArr(arr, MAXSIZE);//long start1 = GetSysTime();//InsertSort_Up(arr, MAXSIZE);//long end1 = GetSysTime();//long start2 = GetSysTime();//ShellSort_Up(arr2, MAXSIZE);//long end2 = GetSysTime();//printf("直接排序%d个数据 耗费时间%d毫秒\n", MAXSIZE, end1 - start1);//printf("希尔排序%d个数据 耗费时间%d毫秒\n", MAXSIZE, end2 - start2);return 0; }

运行结果检测

希尔排序正确性校验


直接插入排序和希尔排序比较

测试10万个数据,直接插入排序和希尔排序的效率


总结

以上是生活随笔为你收集整理的排序算法:希尔排序算法实现及分析的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。