目录
排序算法常见的有(7+1)种:
下面先介绍前七种:
算法一:插入排序(插入排序是一种简单直观的排序方法.)
算法思想:每次将一个需要排序的数据插入到已经排好序的有序数据序列中,从而得到一个新的、个数加一的有序数据序列.
插入排序的基本操作:
- 将待排序序列中第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
- 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面)。
代码实现:
void InsertSort(int* a, int n)
{
assert(a);
for (int i = 1; i < n; ++i)
{
//单个元素排序 第一个元素不需要排序
//找到已经排好序的最后一个元素的位置
int end = i-1;
//把end+1位置元素插入到合适的位置
int tmp = a[i];
while (end>=0 && a[end]>tmp)
{
a[end + 1] = a[end];
--end;
}
//找到合适的位置放
a[end + 1] = tmp;
}
}
int main()
{
int a[] = { 2, 5, 1, 3, 6, 8, 9,122, 4, 7 };
PrintArray(a, 10);
InsertSort(a, 10);
PrintArray(a, 10);
return 0;
}
简单过程图解说明:
小结:
- 时间复杂度 :O(N^2)
- 空间复杂度 :O(1)
- 稳定性 :稳定
- 适合场景 :接近有序序列,时间复杂度趋近于O(N)--> 对于有序序列,时间复杂度O(N)
算法二:希尔排序(缩小增量排序)
希尔排序是插入排序的一种又称“缩小增量排序”,是对直接插入排序算法的一种更高效的改进优化版本。
算法思想(过程):先取一个小于n的整数gap1作为第一个增量,把文件的全部记录分组。所有距离为gap的1倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量gap2<gap1重复上述的分组和排序,直至所取的增量gap =1,即所有记录放在同一组中进行直接插入排序为止。
代码实现:
void ShellSort(int* a, int n)
{
//gap>1 预排序
//gap=1 最终排序过程
int gap=n;
while (gap>1)
{
gap = gap / 3 + 1; //+1是保证最后一次gap为1插入排序
for (int i = gap; i<n; i++)
{
int end = i-gap;
int tmp = a[i];
while (end >= 0 && a[end]>tmp)
{
a[end + gap] = a[end];
end -= gap;
}
a[end + gap] = tmp;
}
}
}
int main()
{
int a[] = { 2, 5, 1, 3, 6, 8, 9, 122, 4, 7 };
PrintArray(a, 10);
ShellSort(a, 10);
PrintArray(a, 10);
return 0;
}
简单过程图解说明:
小结:
- 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序
- 时间复杂度 :平均:O(1.3)--O(N^2)
- 空间复杂度 :O(1)
- 稳定性: 不稳定
算法三:选择排序
基本思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的
数据元素排完 。
基本操作:
- 第一次从待排序的数据序列中选出最小(或最大)的一个数据,存放在序列的起始位置,
- 然后再从剩余的未排序数据序列中寻找到最小(大)数据,然后放到已排序的序列的末尾。
- 以此类推,直到全部待排序的数据的个数为零
代码实现(包含普通写法和优化写法):
//基本写法
//void SelectSort1(int* a, int n)
//{
// int max = 0;
// int i = 0;
// int j = 0;
// for (i = 0; i < n;i++)
// {
// max = a[0];
// for (j = 1; j < n - 1;j++)
// {
// if (a[j]>a[max])
// {
// max = j;
// }
// }
// if (max!=j-1)
// {
// Swap(&a[j - 1], &a[max]);
// }
// }
//
//}
//优化写法
void SelectSort2(int* a, int n)
{
int begain = 0;
int end = n - 1;
while (begain<end)
{
//每一次选一个最大的和最小的,放在相应的位置
int i;
int max;
int min;
max = min = begain;
for (i = begain; i <= end;i++)
{
if (a[i]<a[min])
min = i;
if (a[i]&