目录
0. 前情提醒:
1. 插入排序
1.1 基本思想:
1.2 直接插入排序
实现步骤:
动图演示:
特性总结:
代码实现:
1.3 希尔排序(缩小增量排序)
基本思想:
步骤演示:
特性总结:
代码实现:
2. 交换排序
2.1 基本思想:
2.2 冒泡排序
特性总结:
代码实现:
2.3 快速排序
3.选择排序
3.1 基本思想:
3.2 直接选择排序
步骤思路:
动图演示:
特性总结:
代码实现:
3.3 堆排序
代码实现:
0. 前情提醒:
下面的所有代码实现均为升序
1. 插入排序
1.1 基本思想:
把待排序的记录按其关键码值的大小逐个插入到一个已经排序好的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。
1.2 直接插入排序
实现步骤:
当插入第i(i>=1)各元素时,前面的array[0],array[1],......,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],......的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移
动图演示:
特性总结:
- 元素集合越接近有序,直接插入排序算法的时间效率越高
- 时间复杂度:O(N^2)
- 空间复杂度:O(1),它是一种稳定的排序算法
- 4.稳定性:稳定
代码实现:
void InsertSort(int* a, int n) {
for (int i = 0; i < n; i++) {
int m = a[i];
int end = i;
while (end > 0 && a[end - 1] > m) {
a[end] = a[end - 1];
end--;
}
a[end] = m;
}
}
1.3 希尔排序(缩小增量排序)
基本思想:
先选定一个整数,把待排序的文件中所有(n个)记录分成(n/gap)个组,所有距离为gap的记录分在同一个组,并对每个组内的记录进行排序。然后去gap=gap/2,重复上述分组和排序的工作。当到达gap=1时,所有记录在统一组内排好序(gap=1时就是直接插入排序,gap>1时属于预排序)。
步骤演示:
特性总结:
- 希尔排序是对直接插入排序的优化
- 当gap>1时都是预排序,目的是让数组更接近有序。当gap==1时,数组已经接近有序,这样排序就会很快。这样整体而言,可以达到优化的效果
- 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在不同书上给出的希尔排序的时间复杂度都不一样
代码实现:
void ShellSort(int* a, int n) {
int gap = n;
while (gap > 1) {
gap = gap / 3 + 1;
for (int i = 0; i < n; i++) {
int m = a[i];
int end = i;
while (end > 0 && a[end - gap] > m) {
a[end] = a[end - gap];
end -= gap;
}
a[end] = m;
}
}
}
2. 交换排序
2.1 基本思想:
所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向前部移动
2.2 冒泡排序
左边大于右边交换,一趟排下来最大的在右边
特性总结:
- 冒泡排序是一种非常容易理解的排序
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:稳定
代码实现:
void BubbleSort(int* a, int n) {
for (int i = 0; i < n; i++) {
int k = 1;
for (int j = 0; j < n-i-1; j++) {
if (a[j] > a[j + 1]) {
k = 0;
int x = a[j];
a[j] = a[j + 1];
a[j + 1] = x;
}
}
if (k) {
break;
}
}
}
2.3 快速排序
快速排序较为复杂,想了解请点击-----》快速排序
3.选择排序
3.1 基本思想:
每一次从待排序的数据元素中选出一个最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完
3.2 直接选择排序
步骤思路:
- 在元素array[i]--array[n-1]中选择关键码最小(或最大)的数据元素
- 若它不是这组元素中最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
- 在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素
动图演示:
特性总结:
- 思路很好理解,但效率不好,实际很少应用,主要具有教学意义
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:不稳定
代码实现:
void SelectSort(int* a, int n) {
for (int i = 0; i < n; i++) {
int min = n - 1;
for (int j = i; j < n; j++) {
if (a[min] > a[j]) {
min = j;
}
}
swap(&a[min], &a[i]);
}
}
3.3 堆排序
堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据,利用堆中某个节点的值总是不大于或不小于其父节点的值的特性。注意:升序建大堆,降序建小堆
代码实现:
void AdjustDwon(int* a, int n, int root) {
int i = 2 * root + 1;
if (i < n - 1 && a[i] < a[i + 1]) {
i++;
}
if (i < n && a[root] < a[i]) {
swap(&a[root], &a[i]);
AdjustDwon(a, n, i);
}
}
void HeapSort(int* a, int n) {
//建堆
for (int i = (n - 1 - 1) / 2; i >= 0; i--) {
AdjustDwon(a, n, i);
}
while (n>1) {
swap(&a[0], &a[n-1]);
n--;
AdjustDwon(a, n, 0);
}
}