分类及原理
直接插入排序
模拟排序扑克牌,新牌<旧牌,旧牌依次后移
直接选择排序
从第一个位置开始比较,找出最小的,和第一个位置互换,开始下一轮。
冒泡排序
从左到右,数组中相邻的两个元素进行比较,将较大的放到后面。每一趟排序,最大的数移到最后面,每一趟排序以此交换的次数会减一,因为每一趟排序后,有一个数已经达到指定位置
eg:
趟数 | 元素 |
---|---|
0 | 5 4 3 2 1 |
1 | 4 5 3 2 1 |
1 | 4 3 5 2 1 |
1 | 4 3 2 5 1 |
1 | 4 3 2 1 5 第一趟排序5归位,交换次数:n-1 = 4 |
2 | 3 4 2 1 5 |
2 | 3 2 4 1 5 |
2 | 3 2 1 4 5第二趟排序4归位,交换次数:4-1=3 |
3 | 2 3 1 4 5 |
3 | 2 1 3 4 5第三趟排序3归位,交换次数:3-1=2 |
4 | 1 2 3 4 5第四趟排序2归位,交换次数:2-1=1 |
稳定性定义
举个例子:5,8,5,2,9 我们知道第一遍选择排序第一个元素5会和2交换,那么原序列中2个5的相对位置前后顺序就破坏了
优缺点
这三种算法的优点简单,缺点慢
类型 | 平均 | 最好 | 最坏 | 辅助存储 | 稳定性 |
---|---|---|---|---|---|
直接插入 | O( n 2 n^2 n2) | O(n) | O( n 2 ) n^2) n2) | 1 | 稳定 |
直接选择 | O( n 2 n^2 n2) | O ( n 2 O(n^2 O(n2) | O( n 2 ) n^2) n2) | 1 | 不稳定 |
冒泡 | O( n 2 n^2 n2) | O(n) | O( n 2 ) n^2) n2) | 1 | 稳定 |
C++实现
插入排序
void insert_sort(int* array, int len) {
for (int i = 1; i < len; i++) {
for (int j = i - 1; j >= 0 && array[j] > array[j+1]; j--) {
swap(array[j], array[j + 1]);
}
}
}
直接选择排序
//选择排序
void select_sort(int array[], int array_len)
{
for (int i = 0; i < array_len; i++)
{
int array_min = array[i];
int array_min_index = i;
for (int j = i + 1; j < array_len; j++)//每次选出一个最小值
{
if (array[j] < array_min)
{
array_min = array[j];
array_min_index = j;
}
}
//最小值放到前面,可能会破坏相等数的前后顺序,不稳定
int tmp = array[array_min_index];
array[array_min_index] = array[i];
array[i] = tmp;
}
}
冒泡排序
冒泡排序普通版本
void bubble_sort(int array[], int array_len)
{
for(int i = 0; i < array_len; i++)
{//每次外循环,把当前最大的数移到最后
for(int j = 0; j < array_len - i - 1;j++)
{//内循环,两两比较,每次减少一次比较
if(array[j] > array[j + 1])
{
int tmp = array[j];
array[j] = array[j + 1];
array[j + 1] = tmp;
}
}
}
}
冒泡排序改进版本(加标志位,提前结束)
void bubble_sort(int* array, int len) {
for (int end = len - 1; end > 0; end--) {
bool is_sort = true;
for (int j = 0; j < end; j++) {
if (array[j] > array[j + 1]) {
int tmp = array[j];
array[j] = array[j + 1];
array[j + 1] = tmp;
is_sort = false;
}
}
if(is_sort)
break;
}
}