1.插入排序
(1)算法描述
① 从第一个元素开始,该元素认为已经被排好序;
② 取出下一个元素,在已经排好序的元素序列中从后向前比较;
③ 如果已排好序的元素大于新元素,将该元素移到下一位置;
④ 重复③,直至找到已排好序的元素小于或等于新元素,将新元素插入该位置;
⑤ 重复②③④。
(2)代码实现
//插入排序 时间复杂度:O(n^2)
void insertSort(int* arr, int n)
{
//假设第一个数据已经有序,插入的数据:[1,n]
for (int i = 1; i < n; i++)
{
//从有序数据的最后一个位置向前遍历
int end = i - 1;
int tmp = arr[i];
//while (end >= 0 && arr[end] >= tmp) 不稳定
while (end >= 0 && arr[end] > tmp) //稳定
{
//大的数据向后移动
arr[end + 1] = arr[end];
end--;
}
arr[end + 1] = tmp;
}
}
//输出函数
void printArr(int* arr, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
2.希尔排序
(1)算法描述
① 选择一个递减的增量序列,例如5、2、1;
② 按照增量序列个数k,对序列进行k趟排序;
③ 每趟排序,根据对应的增量,将待排序的序列分割成若干长度为m的子序列,对子序列进行插入排序,最后一趟排序,间隔必须是1,保证所有的数据在同一个序列中。
(2)代码实现
//希尔排序 时间复杂度O(n^1.3) 不稳定
void shellSort(int* arr, int n)
{
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;
//最后一趟排序,间隔必须是1,保证所有数据在同一组
//一趟希尔排序
for (int i = gap; i < n; i++)
{
//同组数据,最后一个有序的数据的位置
int end = i - gap;
//待插入的数据
int data = arr[i];
while (end >= 0 && arr[end] > data)
{
arr[end + gap] = arr[end];
end -= gap;
}
arr[end + gap] = data;
}
}
}
3.选择排序
(1)算法描述
① 初始状态:未排序的区间[1,n];
② 第i趟排序开始时,当前有序区间和无序区间分别为[i,i-1]、[i,n],从无序区间找到最小值,然后将其与无序区间的第一个值交换,更新有序和无序区间;
③ 重复②,直至n-1趟结束,数据有序。
(2)代码实现
//选择排序 时间复杂度:O(n^2) 稳定
void selectSort1(int* arr, int n)
{
//从未排序的序列中找出最值,存放在未排序的起始位置
//未排序区间[start,end];
int start = 0;
int end = n - 1;
while (start < end)
{
//找到最小值位置
int minidx = start;
for (int i = start + 1; i <= end; i++)
{
//if (arr[i] <= arr[minidx]) 不稳定
if (arr[i] < arr[minidx])
minidx = i;
}
//把最小值存到最开始的位置
swap(arr, start, minidx);
//剩余未排序的位置区间[start + 1, end];
++start;
}
}
//遍历的次数减少一半的选择排序
void selectSort2(int* arr, int n)
{
int start = 0;
int end = n - 1;
//每次未排序的区间找到一个最大值和最小值
//最小值放在头部,最大值放在尾部
while (start < end)
{
int minidx = start;
int maxidx = start;
for (int j = start + 1; j <= end; j++)
{
if (arr[j] < arr[minidx])
minidx = j;
if (arr[j] > arr[maxidx])
maxidx = j;
}
//把最小值存放在最开始的位置
swap(arr, start, minidx);
//判断最大值的位置是否在起始位置
if (maxidx == start)
maxidx = minidx;
//最大值存放在末尾
swap(arr, end, maxidx);
++start;
--end;
}
}
4. 冒泡排序
(1)算法描述
① 比较相邻的元素,如果第一个元素大于第二个,交换;
② 对每一对相邻元素进行①(第一次遍历完成后,最后一个数即为最大数);
③ 重复执行②,直至排序完成。
(2)代码实现
//冒泡排序 时间复杂度O(n^2) 数据有序:O(n) 稳定
void bubbleSort(int* arr, int n)
{
//相邻元素进行比较
//第一次遍历的范围:0~未排序数据的最后一个位置
//flag:标记一轮冒泡排序中是否发生了交换
int flag = 0;
int end = n;
while (end > 1)
{
//一轮冒泡排序
for (int i = 1; i < end; ++i)
{
if (arr[i - 1] > arr[i]) {
//大的数向后移动
swap(arr, i - 1, i);
flag = 1;
}
}
//如果没有发生交换,说明剩余元素全部有序
if (!flag)
break;
--end;
}
}