希尔排序(Shell Sort)
视频教程:【十大排序算法】用可视化动画讲希尔排序
1、简单插入排序的问题
测试数据:5,6,7,8,9,1
说明:插入1的时候需要比较其它所有的数。
问题:当需要插入的数是较小的数时,后移的次数明显增多,对效率有影响。
2、介绍
希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。
3、算法步骤
希尔排序是把元素按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的元素越来越多,当增量减至 1 时,整个序列恰被分成一组,排序完后算法便终止。
4、代码实现
1、Java版代码
package sort;
import java.util.Arrays;
import java.util.Iterator;
public class ShellSort {
public static void main(String[] args) {
int[] arr = { 69,22,81,24,9,38 };
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
// 希尔排序
public static void shellSort(int[] arr) {
/**
* compareIndex:比较值的下标
* readyInsertVal:待插入值
* readyInsertIndex:待插入值下标
* gap: 增量
*/
int compareIndex;
int readyInsertVal;
// gap从数组长度一半开始,每次对gap除2,减少到1。
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
// readyInsertIndex从gap开始,到数组最后一个
for (int readyInsertIndex = gap; readyInsertIndex < arr.length; readyInsertIndex++) {
// 每轮开始时,比较值为待插入值前gap个
compareIndex = readyInsertIndex - gap;
readyInsertVal = arr[readyInsertIndex];
// 待插入值小于比较值
if (readyInsertVal < arr[compareIndex]) {
// 找到适当位置,比较值的下标没有越界且待插入值小于比较值
while (compareIndex >= 0 && readyInsertVal < arr[compareIndex]) {
// 比较值后移gap个位置
arr[compareIndex + gap] = arr[compareIndex];
// 更换比较值为前gap个值
compareIndex -= gap;
}
// 待插入值插入到比较值的后gap个位置
arr[compareIndex + gap] = readyInsertVal;
}
}
}
}
}
2、C语言版代码
#include<stdio.h>
#define len 6
void shellSort(int arr[]) {
/**
* compareIndex:比较值的下标
* readyInsertVal:待插入值
* readyInsertIndex:待插入值下标
* gap: 增量
*/
int compareIndex;
int readyInsertVal;
int gap;
int readyInsertIndex;
// gap从数组长度一半开始,每次对gap除2,减少到1。
for (gap = len / 2; gap > 0; gap /= 2) {
// readyInsertIndex从gap开始,到数组最后一个
for (readyInsertIndex = gap; readyInsertIndex < len; readyInsertIndex++) {
// 每轮开始时,比较值为待插入值前gap个
compareIndex = readyInsertIndex - gap;
readyInsertVal = arr[readyInsertIndex];
// 待插入值小于比较值
if (readyInsertVal < arr[compareIndex]) {
// 找到适当位置,比较值的下标没有越界且待插入值小于比较值
while (compareIndex >= 0 && readyInsertVal < arr[compareIndex]) {
// 比较值后移gap个位置
arr[compareIndex + gap] = arr[compareIndex];
// 更换比较值为前gap个值
compareIndex -= gap;
}
// 待插入值插入到比较值的后gap个位置
arr[compareIndex + gap] = readyInsertVal;
}
}
}
}
int main() {
int arr[] = {69,22,81,24,9,38};
int i;
printf("排序后:\n");
shellSort(arr);
for(i=0; i < len; i++) {
printf("%d ", arr[i]);
}
}
5、时空复杂度
平均时间复杂度:O(nlogn)
比较难证明,初学者先掌握代码实现即可。
空间复杂度:O(1)
排序过程中只用到几个辅助变量
6、稳定性
希尔排序是不稳定的排序算法
稳定性:排序前两个值相等的元素的前后位置顺序和排序后它们两个的前后位置顺序相同
7、结束语
打开微信扫描小程序码体验希尔排序动画演示: