直接插入排序、希尔排序,直接选择排序
一.直接插入排序
1. 什么是插入排序
a. 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
2.算法基本步骤
b. 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
3.动图演示(升序)
4.图形演示
✈✈✈第一趟排序
end = 0;
✈✈✈第二趟排序
end = 1;
✈✈✈第三趟排序
end = 2;
✈✈✈第四趟排序
end = 3;
代码实现
//直接插入排序
void InserSort(int* a, int size)
{
for (int i = 0; i < size - 1; ++i)
{
int end = i;
int tmp = a[end + 1];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + 1] = a[end];
--end;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
二.希尔排序
1.什么是希尔排序
a. 希尔排序,是插入排序的一种更高效的改进版本,希尔排序是基于插入排序的以下两点性质而提出改进方法的:
☂ 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
☂但插入排序一般来说是低效的,因为插入排序每次只能将数据向前(向后)移动一位;
希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
2.算法基本步骤
b. 先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作…
c.当增量的大小减到1时,就相当于整个序列被分到一组,进行一次直接插入排序,排序完成。
3. 动图演示
4.图形演示
gap折半,把待排序列分成五组,每组两个元素,然后分别对五组数据进行直接插入排序。
gap折半,把待排序列分成两组,每组五个元素,然后分别对五组数据进行直接插入排序。。
gap折半,把待排序列分成一组,每组十个元素,然后分别对五组数据进行直接插入排序(gap等于1,已经是直接插入排序了)。
代码实现
//希尔排序
void ShellSort(int* a, int size)
{
int gap = size;
while (gap > 1)
{
gap = gap / 2;
for (int i = 0; i < size - gap; ++i)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}
}
三.直接选择排序
1.什么是直接选择排序
a. 顾名思义,假设我们要排一个升序序列,我们就要遍历待排序,选出最大和最小的,把它们放到相应的位置,然后再出没有排好的序列里找出最大和最小的,放的相应的位置,反复这样,直到排好。
2.算法基本步骤
其实这个算法的思想特别简单,就像打擂台一样,我们假设第一个上去的人就是最能打的,然后让后面的人依次与大,到最后还站在的那个人就是最能打的,然后我们在从剩下的人里假设一个最能打的,在进行上面的步骤,直到最后排好。选择最不能打的一样。
3. 动图演示
4.代码实现
//直接选择排序
void SelectSort(int* a, int size)
{
int begin = 0;
int end = size - 1;
while (begin < end)
{
int mini = begin;
int maxi = begin;
for (int i = begin; i <= end; i++)
{
if (a[i] < a[mini])
{
mini = i;
}
if (a[i] > a[maxi])
{
maxi = i;
}
}
Swap(&a[begin], &a[mini]);
//如果begin与maxi重叠,需要修正一下maxi
if (begin == maxi)
{
maxi = mini;
}
Swap(&a[end], &a[maxi]);
begin++;
end--;
}
}