冒泡排序、插入排序、选择排序、希尔排序 时间复杂度 O(N²)
稳定性: 这个概念是说,如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间原有的先后顺序不变。
原地排序算法:特指空间复杂度是O(1)的排序算法。
开始前一句话总结
-
冒泡排序
就是找最大的数,从左到右一一对比,每一个下标都会和后面每个数对比一次,比右侧大,数据对换; -
选择排序
就是找最小的数,从左到右一一对比并记录最小数下标,得到最小数下标,数据对换 -
插入排序
就是分为已排序区和未排序区,从左到右依次插入到对应位置已排序区 -
希尔排序
和插入很相似都是分为已排序区和未排序区,而是采用跳跃式对比,先做出基本有序后,在最后进行插入排序,从而提高排序速度。
冒泡排序
function bubbleSort($arr)
{
$len = count($arr);
for ($i = 1; $i < $len; $i++) {
for ($k = 0; $k < $len - $i; $k++) {
if ($arr[$k] > $arr[$k + 1]) {
$tmp = $arr[$k + 1];
$arr[$k + 1] = $arr[$k];
$arr[$k] = $tmp;
}
}
}
return $arr;
}
时间复杂度: O(N²)
空间复杂度: O(1)
稳定、原地排序算法
冒泡比较简单,从左到右,相邻比较。
插入排序
function insertSort($arr)
{
$len = count($arr);
for ($i = 1; $i < $len; $i++) {
$val = $arr[$i];
for ($j = $i - 1; $j >= 0; $j--) {
if ($arr[$j] > $val) {
$arr[$j + 1] = $arr[$j];
} else {
break;
}
}
$arr[$j + 1] = $val;
}
return $arr;
}
时间复杂度: O(N²)
空间复杂度: O(1)
稳定、原地排序算法
排序描述
为什么叫插入排序,很容易就联想到一个有序的数组,我们往里面添加一个新的数据后,如何继续保持数据有序呢?很简单,我们只要遍历数组,找到数据应该插入的位置将其插入即可。如下图已有一个数组:
首先我们将数组中的数据分为两个区间,
已排序区间
和未排序区间
。
- 初始数组只有一个元素 4 (4就是已排序区间)
- 这时未排序区间内 5 要插入,判断是否大于 4,不大于放到已排序区间(当然这种说话只是为了方便理解,其实就是数组元素不动)
- 一直到 1 的时候小于已排序区间插入到已排序区间对应位置也就是第一个位置(写代码时就是和已排序区间每个值对比,一直找到比 1 小的最前位置)
- 一值循环对比,最后完成
选择排序
function selectSort($arr)
{
$len = count($arr);
for ($i = 0; $i < $len-1; $i++) {
$min_index = $i;
for ($j = $i + 1; $j < $len; $j++) {
if ($arr[$j] < $arr[$min_index]) {
$min_index = $j;
}
}
if ($i != $min_index) {
$tmp = $arr[$i];
$arr[$i] = $arr[$min_index];
$arr[$min_index] = $tmp;
}
}
return $arr;
}
时间复杂度: O(N²)
空间复杂度: O(1)
不稳定、原地排序算法
排序描述
选择排序算法的实现思路有点类似插入排序,也分已排序区间
和未排序区间
。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。
为什么是不稳定的排序算法
比如 5,8,5,2,9 这样一组数据,使用选择排序算法来排序的话,第一次找到最小元素 2,与第一个 5 交换位置,那第一个 5 和中间的 5 顺序就变了,所以就不稳定了。正是因此,相对于冒泡排序和插入排序,选择排序就稍微逊色了。
希尔排序
function shellSort(&$arr)
{
$count = count($arr);
$inc = $count;
do {
$inc = ceil($inc / 2);
for ($i = $inc; $i < $count; $i++) {
$tmp = $arr[$i];
for ($j = $i - $inc; $j >= 0 && $arr[$j + $inc] < $arr[$j]; $j -= $inc) {
$arr[$j + $inc] = $arr[$j];
}
$arr[$j + $inc] = $tmp;
}
} while ($inc > 1);
}
排序描述
希尔排序就是插入排序的一种改进,插入排序在基本有序或记录数比较少时效率会高。
希尔就是利用分组和基本有序来提升效率。
一个数组$arr = [9, 1, 5, 8, 3, 7, 4, 6, 2];
最关键就是怎么把它变成一个基本有序,什么是基本有序呢,就是基本小数在左,不大不小在中间,大数在右
比如像 [2, 1, 3, 6, 4, 7, 5, 8, 9]
这样可以称为基本有序,怎么实现的呢,下面简单描述下过程,然后看代码去领悟其中含义。
第一轮 $inc=5
时,i 从 5 循环到 8,j = i - inc
,$inc = ceil($inc / 2);
= 9/2 =
5`
- i =
5
,j = 0;$arr[$j + $inc] < $arr[$j]
=$arr[5] < $arr[0]
=7 < 9
变换位置
数组变成[7, 1, 5, 8, 3, 9, 4, 6, 2]
- i =
6
,j = 1;$arr[$j + $inc] < $arr[$j]
=$arr[6] < $arr[1]
=9 < 1
所以不变换位置 - i =
7
,j = 2;$arr[$j + $inc] < $arr[$j]
=$arr[7] < $arr[2]
=6 < 5
所以不变换位置 - i =
8
,j = 3;$arr[$j + $inc] < $arr[$j]
=$arr[8] < $arr[3]
=2 < 8
变换位置
数组变成[7, 1, 5, 2, 3, 9, 4, 6, 8]
第二轮 $inc=3
时,i 从 3 循环到 8 ,j = i - inc
,$inc = ceil($inc / 2);
= 5/2 =
3`
- i =
3
,j = 0;$arr[3] < $arr[0]
=2 < 7
变换位置
数组变成[2, 1, 5, 7, 3, 9, 4, 6, 8]
- i =
4
,j = 1;$arr[4] < $arr[1]
=3 < 1
所以不变换位置 - i =
5
,j = 2;$arr[5] < $arr[2]
=9 < 5
所以不变换位置 - i =
6
,j = 3;$arr[6] < $arr[3]
=4 < 7
变换位置
数组变成[2, 1, 5, 4, 3, 9, 7, 6, 8]
- i =
7
,j = 4;$arr[7] < $arr[4]
=6 < 3
所以不变换位置 - i =
8
,j = 5;$arr[8] < $arr[5]
=8 < 9
变换位置
数组变成[2, 1, 5, 4, 3, 8, 7, 6, 9]
第三轮 $inc = 2
时,i 从 2 循环到 8 ,j = i - inc
,$inc = intval(3 / 2);
= 3/2
= 2
- i =
2
,j = 0;$arr[2] < $arr[0]
=5 < 2
所以不变换位置 - i =
3
,j = 1;$arr[3] < $arr[1]
=4 < 1
所以不变换位置 - i =
4
,j = 2;$arr[4] < $arr[2]
=3 < 5
变换位置
数组变成[2, 1, 3, 4, 5, 8, 7, 6, 9]
- i =
5
,j = 3;$arr[5] < $arr[3]
=8 < 4
所以不变换位置 - i =
6
,j = 4;$arr[6] < $arr[4]
=7 < 5
所以不变换位置 - i =
7
,j = 5;$arr[7] < $arr[5]
=6 < 8
变换位置
数组变成[2, 1, 3, 4, 5, 6, 7, 8, 9]
- i =
8
,j = 6;$arr[8] < $arr[6]
=8 < 9
所以不变换位置
第四轮 $inc = 1
时,i 从 1 循环到 8 ,j = i - inc
,$inc = intval($inc / 3) + 1;
= 2/3+1
= 1
- i =
1
,j = 0;$arr[1] < $arr[0]
=1 < 2
变换位置
数组变成[1, 2, 3, 4, 5, 6, 7, 8, 9]
- i =
2
,j = 1;$arr[2] < $arr[1]
=3 < 2
所以不变换位置 - i =
3
,j = 2;$arr[3] < $arr[2]
=4 < 3
所以不变换位置 - i =
4
,j = 3;$arr[4] < $arr[3]
=5 < 4
所以不变换位置 - i =
5
,j = 4;$arr[5] < $arr[4]
=6 < 5
所以不变换位置 - i =
6
,j = 5;$arr[6] < $arr[5]
=7 < 6
所以不变换位置 - i =
7
,j = 6;$arr[7] < $arr[6]
=8 < 7
所以不变换位置 - i =
8
,j = 7;$arr[8] < $arr[7]
=9 < 8
所以不变换位置
[1, 2, 3, 4, 6, 5, 7, 8, 9]