一、插入排序
- 插入排序由N-1趟排序组成(第一个元素不需要执行插入操作),插入排序利用这样一个事实:对于第p趟,位置0到位置p-1上的元素为已排好序的状态。所以在第p趟,只需让位置p上的元素向左逐个比较找到合适插入的位置。
- 代码实现
template <typename T>
void InsertionSort(vector<T>& a)
{
for (int p = 1; p < a.size(); ++p)
{
int tmp = move(a[p]);//将待插入元素移交给哨兵
int j;
//从后往前查找待插入的位置
for (j = p; j > 0 && tmp < a[j - 1]; --j)
{
a[j] = move(a[j - 1]);
}
//移动待插入元素到插入位置
a[j] = move(tmp);
}
}
代码中内层for循环意思是:判断第p趟时a[p]是否小于a[p-1],如果是,则a[p-1]向后(右)移动一个位置。
注意:for循环中条件不满足时,会跳出不执行循环体和--j.(之前本人对for循环原理模糊导致无法理解插入排序代码原理,特此标注)。
二、希尔排序(C++实现)
1.代码如下:
template <typename T>
void ShellSort(vector<T>& a)
{
for (int gap = a.size()/2; gap>0; gap/=2)
{
for (int p = gap; p < a.size(); ++p)
{
int tmp = move(a[p]);//将待插入元素移交给哨兵
int j;
//从后往前查找待插入的位置
for (j = p; j > gap-1 && tmp < a[j - gap]; j-=gap)
{
a[j] = move(a[j - gap]);
}
//移动待插入元素到插入位置
a[j] = move(tmp);
}
}
}
希尔排序需要定义一个增量,这里选择增量为gap=序列长度/2,缩小增量以gap=gap/2的方式 。
2.记忆技巧
对比插入排序:在插入排序外套了一层for循环,用的是希尔推荐的希尔增量。再将原来插入排序代码中所有的1换成gap,而0自然就换成gap-1.例如上述代码中j--就换成j-=gap.