tem = 5时和end = 7比较,tem < end,
end--,继续和4比较大于4,所以7后移,然后将tem赋值给end+1的位置,
tem = 1时 和end = 7比较,一直比较到2.
tem= 1 小于 end = 2 所以end --
此时end走到头,结束,将 2,4,7 均向后移动。
然后将tem =1 赋值给end+1的位置。
2.2.1 单趟直接插入排序实现
c复制代码
//升序
void insertSort(int* a, int n)
{
//先写单趟排序,再整体排序
int end ;//end是0位置
int tem ;//tem 就是end后面1个位置
while (end >= 0)
{
if (tem < a[end])
{
//一个一个插入,当要插入值小于end位置的值,end位置往后的值都要往后移
a[end + 1] = a[end];
--end;//更新end的值
}
else
{
break; //这里是比较巧妙的做法,当我们插入值大于end的时候直接跳出,
}
}
a[end + 1] = tem; //不论我们分析的1或者5两种情况,tem的值都赋值给了end+1位置
}
2.2.2 整体直接插入排序实现
c复制代码
//升序
void insertSort(int* a, int n)
{
int i = 0;
for (i = 1; i < n ; i++) //从1 开始从n结束,如果是0开始就是n-1结束
{
//先写单趟排序,再整体排序
int end = i-1;//end是0位置
int tem =a[i];//tem 就是end后面1个位置
while (end >= 0)
{
if (tem < a[end])
{
//一个一个插入,当要插入值小于end位置的值,end位置往后的值都要往后移
a[end + 1] = a[end];
--end;//更新end的值
}
else
{
break;
}
}
a[end + 1] = tem;
}
}
我们的gap是按照Knuth提出的方式取值的,即gap/=2 或者 gap = gap /3 +1,而且Knuth进行了大量的试验统计,暂时就按照:O(n1.25) ~ O(1.6*n1.25)来算
稳定性:不稳定
3.2 希尔排序代码实现
3.2.1单趟排序代码实现
单趟希尔排序思路图解
间隔为gap分为一组对每组数据插入排序 gap = 3
蓝色是一组
橙色是一组
绿色是一组
单趟希尔排序代码实现
c复制代码
//希尔排序
void shellSort(int* a, int n)
{
int i = 0;
int gap = 3; //这是我们自己随便定的
for (i = 0; i < n-1; i += gap)
{
int end= i; //end最开始就是0
int tem = a[i + gap];//tem 是end后一个位置(间隔gap)
while (end >= 0)
{
if (tem < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tem;
}
}
//希尔排序
void shellSort(int* a, int n)
{
int i = 0;
int gap = 3;
int j = 0;
for (j = 0; j < gap; j++) //gap 是几 就分几组,所以在最外层加一层循环
{
for (i = j; i < n - gap; i += gap)//这里i 从j开始,最开始
{
int end = i; //end最开始就是0
int tem = a[i + gap];//tem 是end后一个位置(间隔gap)
while (end >= 0)
{
if (tem < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tem;
}
}
}
3.2.3 gap希尔排序代码实现2------不分组进行,同步进行
代码详细图解
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i= 6
实现代码
c复制代码
//希尔排序
void shellSort(int* a, int n)
{
int i = 0;
int gap = 3;
int j = 0;
#if 0
for (j = 0; j < gap; j++) //gap 是几 就分几组,所以在最外层加一层循环
{
for (i = j; i < n - gap; i += gap)//这里i 从j开始,最开始
{
int end = i; //end最开始就是0
int tem = a[i + gap];//tem 是end后一个位置(间隔gap)
while (end >= 0)
{
if (tem < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tem;
}
}
#endif
#if 1
for (i = j; i < n - gap; i++)//这里i 从j开始,最开始
{
int end = i; //end最开始就是0
int tem = a[i + gap];//tem 是end后一个位置(间隔gap)
while (end >= 0)
{
if (tem < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tem;
}
#endif
}
代码验证
经过3.2.2 和3.2.3 小结我们发现最终结果并不是有序的,这说明我们的gap取值不够精确
3.2.4 希尔排序代码最终实现版本(采用3.2.3的实现思想)
gap的取值,目前我们采用gap /=2 或者 gap = gap/3+1
c复制代码
//希尔排序
void shellSort(int* a, int n)
{
int i = 0;
int gap = n;
int j = 0;
#if 0
for (j = 0; j < gap; j++) //gap 是几 就分几组,所以在最外层加一层循环
{
for (i = j; i < n - gap; i += gap)//这里i 从j开始,最开始
{
int end = i; //end最开始就是0
int tem = a[i + gap];//tem 是end后一个位置(间隔gap)
while (end >= 0)
{
if (tem < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tem;
}
}
#endif
#if 1
while (gap > 1)
{
gap /= 2;
for (i = j; i < n - gap; i++)//这里i 从j开始,最开始
{
int end = i; //end最开始就是0
int tem = a[i + gap];//tem 是end后一个位置(间隔gap)
while (end >= 0)
{
if (tem < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tem;
}
}
#endif
}
验证1
验证2
4 附录-插入排序源码
4.1 sort.h
c复制代码
#pragma once
#include<stdio.h>
void printArray(int* a, int n);
void insertSort(int* a, int n);
void shellSort(int* a, int n);
4.2 sort .c
c复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"20250320_sort.h"
void printArray(int* a, int n)
{
int i = 0;
for (i = 0; i < n; i++)
{
//printf("%d ", *(a + i));
printf("%d ", a[i]);
}
printf("\n");
}
//升序
void insertSort(int* a, int n)
{
int i = 0;
for (i = 1; i < n; i++) //从1 开始从n结束,如果是0开始就是n-1结束
{
//先写单趟排序,再整体排序
int end = i - 1;//end是0位置
int tem = a[i];//tem 就是end后面1个位置
while (end >= 0)
{
if (tem < a[end])
{
//一个一个插入,当要插入值小于end位置的值,end位置往后的值都要往后移
a[end + 1] = a[end];
--end;//更新end的值
}
else
{
break;
}
}
a[end + 1] = tem;
}
}
//希尔排序
void shellSort(int* a, int n)
{
int i = 0;
int gap = n;
int j = 0;
#if 0
for (j = 0; j < gap; j++) //gap 是几 就分几组,所以在最外层加一层循环
{
for (i = j; i < n - gap; i += gap)//这里i 从j开始,最开始
{
int end = i; //end最开始就是0
int tem = a[i + gap];//tem 是end后一个位置(间隔gap)
while (end >= 0)
{
if (tem < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tem;
}
}
#endif
#if 1
while (gap > 1)
{
// gap /= 2;
gap = gap/3 + 1;
for (i = j; i < n - gap; i++)//这里i 从j开始,最开始
{
int end = i; //end最开始就是0
int tem = a[i + gap];//tem 是end后一个位置(间隔gap)
while (end >= 0)
{
if (tem < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tem;
}
}
#endif
}