希尔排序
来源:互联网 发布:数据库的导入和导出 编辑:程序博客网 时间:2024/06/05 19:13
希尔排序其实是直接插入排序的一个拓展。虽然没有直接证明说明希尔排序比直接插入排序快,但是在并行运算上,希尔排序的确十分优秀。而且这是一个不稳定的排序算法。
为什么用希尔排序: 直接插入排序有个不足之处是当一个数组是十分无序的状态时,排序的时间复杂度较久。特别是要将一个逆序的数组排为顺序的数组,这个逆序的数组相当于完全无序的,而直接插入排序需要的时间久。(数据多时,且无序)而如何使排序时间减少呢,那么对数据有一定的要求,那就是基本有序。利用希尔排序,可以使数据先基本有序,然后在利用直接插入法。直接插入排序在数据量少时效率还是挺高的,所以就先将数组分开一小组一小组的排,最后使得整个数组是基本有序状态,再用一次直接插入排序法即可。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
1,插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
2,插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
基本思想:其实是一种分组插入方法。希尔排序是把数据按下标的一定增量分组d={d1,d2,3,d4,…,dn=1},增量相当于分的组数,而数组长度/增量≈每组中的元素。对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的数据越来越多,当增量减至1时,所有数据恰被分成一组,算法便终止。
//主要函数:void shellSort(List *list, int d[], int num); //希尔排序void shellInsert(List * list, int dk); //分组直接插入排序List * initList(List * list, int len); //初始化
初始化函数:为list分配空间,指定长度,然后给数组赋值随机数。
List * initList(List * list, int len){ list = (List *)malloc(sizeof(List)); list->length = len; list->data = malloc(sizeof(int) * len); srand((unsigned)time(NULL)); for (int i = 0; i < len; i++) { list->data[i] = rand() % 100; } return list;}
直接插入排序函数:
这里与直接插入排序函数没有太大区别,直接插入排序法可参考这篇blog:
http://blog.csdn.net/sherilindas/article/details/51893511
这里主要的区别是排序时进行了分组。
传入的参数为缩小增量,通过增量给整个数组分组。例如下图。
这时增量d=5,所以共有5组,每组有数组长度/增量d=2个。
于是就在每组中进行插入排序。循环重复条件直到length – d,也即是下图此处。
void shellInsert(List * list, int dk) //dk即为增量 { int temp = 0; //temp设为哨兵位,即用于储存抽出来的元素 for (int i = 0; i < list->length - dk; i++) { //当此元素比此组的下一个元素要大时开始交换 if (list->data[i] > list->data[i + dk]) { temp = list->data[i + dk]; //抽取小的元素 int j = i + dk; //组内比temp小的元素全部往后移 while (j> 0&&temp < list->data[j - dk]) { list->data[j] = list->data[j - dk]; j = j - dk; } //将temp放入前面 list->data[j] = temp; } } return;}
而shellSort函数主要负责改变增量,随着增量的减小,每组中的数据会增加。直到增量变为1,这时就只有一组数据,这时整个数组已经基本有序。
void shellSort(List *list, int d[], int num) //d为增量序列,num为增量序列长度{ for (int i = 0; i < num; i++) { shellInsert(list, d[i]); //每次循环改变增量 } return;}
这里举一个例子:假如数组为{49,38,65,97,76,13,27,49,55,04},数组长度为10,增量序列为d={5,3,1}
第一趟增量d=5,分为5组,分别进行直接插入排序。
最后结果为(13,27,49,55,04,49,38,65,97,76)
第二趟增量d=3,分为3组,分别进行直接插入排序。
最后结果为(13,04,49,38,27,49,55,65,97,76)
第三趟增量d=1,分为1组,这是数组已经基本有序,直接插入排序。
以下为源文件:
#include <stdio.h>#include <stdlib.h>#include <time.h>typedef struct List{ int *data; int length;}List;void shellSort(List *list, int d[], int num);void shellInsert(List * list, int dk);List * initList(List * list, int len);void shellSort(List *list, int d[], int num){ for (int i = 0; i < num; i++) { shellInsert(list, d[i]); } return;}void shellInsert(List * list, int dk){ int temp = 0; for (int i = 0; i < list->length - dk; i++) { if (list->data[i] > list->data[i + dk]) { temp = list->data[i + dk]; int j = i + dk; while (j> 0&&temp < list->data[j - dk]) { list->data[j] = list->data[j - dk]; j = j - dk; } list->data[j] = temp; } } return;}List * initList(List * list, int len){ list = (List *)malloc(sizeof(List)); list->length = len; list->data = malloc(sizeof(int) * len); srand((unsigned)time(NULL)); for (int i = 0; i < len; i++) { list->data[i] = rand() % 100; } return list;}void printList(List * list){ for (int i = 0; i < list->length; i++) { printf("%d ", list->data[i]); } printf("\n\n"); return;}int main(){ List * list = NULL; int d[3] = { 5,3,1 }; list = initList(list, 10); printList(list); shellSort(list, d, 3); printList(list); return 0;}
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 希尔排序
- 快速排序
- Linux设置Gnome终端半透明方案
- css3制作魔方
- 让你的jQuery提升一个台阶
- 1018. Public Bike Management (30)
- 希尔排序
- Android 在 SElinux下 如何获得对一个内核节点的访问权限
- 【媒体信号处理】No.2 一维DCT变换
- 浅谈图片服务器的架构演进
- 以POST方式下载文件
- Python_共轭梯度法与最速下降法之间的比较
- css3元素周期表
- tinyhttpd 学习笔记
- Android 获取内外置存储路径