希尔排序的简介:
就是简单的插入排序(如冒泡排序)的升级版,就是一个特殊的插入排序,将一整个数列,分成n组,将每一组进行排序,然后再合并为n/2组,然后在对每一组进行排序,知道最后只剩一组。
宏观简介:
图片取自( https://www.cnblogs.com/chengxiao/p/6104371.html )
插曲:for循环的执行顺序:
for 循环语句的一般形式为:
for (表达式1; 表达式2; 表达式3)
{
语句;
}
下面来看看它的执行过程:
- 求解表达式1。
- 求解表达式2。若其值为真,则执行 for 语句中指定的内嵌语句,然后执行第3步;若表达式2值为假,则结束循环,转到第5步。
- 求解表达式3。
- 转回上面第2步继续执行。
- 循环结束,执行 for 语句下面的语句。
从这个执行过程中可以看出,“表达式1”只执行一次,循环是在“表达式2”“表达式3”和“内嵌语句”之间进行的。也就是说,for循环语句一开始就要判断表达式2是否成立。
代码详细阐述:
#include <stdio.h>
int main()
{
int arr[10] = { 69,56,12,136,3,55,46,99,88,25, };
int i,j,gap,temp;
for (gap = 10/2; gap > 0; gap/=2) {
//这里的gap不仅表示分成几组,也表示在一组数列内,两个元素相距的距离
for (i = gap; i < 10; i++) {
//这里是表示将每一组都排序一遍
for (j = i - gap; j >= 0; j-=gap){
//这里是将每一组的每个元素都比较一遍
if (arr[j] > arr[j + gap]) {//只需要将前面的一半与后面的一半进行比较即可
temp = arr[j + gap];
arr[j + gap] = arr[j];
arr[j] = temp;
}
//这个for循环,第二次看的时候有点不理解:为什么只需要两两对比,而不需要一个与所有对比。
就拿上面的例子来说明,初始数列为:
8,9,1,7,2,3,5,4,6,0
第一轮过后:
3,5,1,6,0,8,9,4,7,2
第二轮过后:
。。。。。
发现这种方法很难以理解,直接使用定义方法来做,就是直接将其分组,然后在使用插入排序
}
}
}
printf("排序后的数组为:\n");
for (i = 0; i < 10; i++)
printf("%d,", arr[i]);
return 0;
}
用下面这个算法更好理解:
#include <stdio.h>
int main()
{
int arr[10] = { 69,56,12,136,3,55,46,99,88,25, };
int i, j, gap, temp;
for (gap = 10 / 2; gap > 0; gap /= 2) {
//这里的gap不仅表示分成几组,也表示在一组数列内,两个元素相距的距离
for (i = gap; i < 10; i++) {
//这里是表示将每一组都排序一遍
temp = arr[i];
for (j = i - gap; j >= 0 && arr[j]>temp; j -= gap) {
//这里是将每一组的每个元素都比较一遍
arr[j + gap] = arr[j];
}
arr[j + gap] = temp;
}
}
printf("排序后的数组为:\n");
for (i = 0; i < 10; i++)
printf("%d,", arr[i]);
return 0;
}