# PHP面试：尽可能多的说出你知道的排序算法

### 排序和他们的类型

• Bubble sort
• Insertion sort
• Selection sort
• Quick sort
• Merge sort
• Bucket sort

### 冒泡排序

``````procedure bubbleSort(A: list of sortable items)
n = length(A)
for i = 0 to n inclusive do
for j = 0 to n - 1 inclusive do
if A[j] > A[j + 1] then
swap(A[j + 1], A[j])
end if
end for
end for
end procedure``````

``````function bubbleSort(&\$arr) : void
{
\$swapped = false;
for (\$i = 0, \$c = count(\$arr); \$i < \$c; \$i++) {
for (\$j = 0; \$j < \$c - 1; \$j ++) {
if (\$arr[\$j + 1] < \$arr[\$j]) {
list(\$arr[\$j], \$arr[\$j + 1]) = array(\$arr[\$j + 1], \$arr[\$j]);
}
}
}
}``````

#### 冒泡排序的复杂度分析

best time complexity Ω(n)
worst time complexity O(n2)
average time complexity Θ(n2)
space complexity (worst case) O(1)

#### 冒泡排序的改进

``````procedure bubbleSort(A: list of sortable items)
n = length(A)
for i = 1 to n inclusive do
swapped = false
for j = i to n - 1 inclusive do
if A[j] > A[j + 1] then
swap(A[j], A[j + 1])
swapped = true
endif
end for
if swapped = false
break
endif
end for
end procedure
``````

``````function bubbleSort(&\$arr) : void
{
for (\$i = 0, \$c = count(\$arr); \$i < \$c; \$i++) {
\$swapped = false;
for (\$j = 0; \$j < \$c - 1; \$j++) {
if (\$arr[\$j + 1] < \$arr[\$j]) {
list(\$arr[\$j], \$arr[\$j + 1]) = array(\$arr[\$j + 1], \$arr[\$j]);
\$swapped = true;
}
}

if (!\$swapped) break; //没有发生交换，算法结束
}
}``````

``````procedure bubbleSort(A: list of sortable items)
n = length(A)
for i = 1 to n inclusive do
swapped = false
for j = 1 to n - i - 1 inclusive do
if A[j] > A[j + 1] then
swap(A[j], A[j + 1])
swapped = true
endif
end for
if swapped = false
break
end if
end for
end procedure
``````

``````function bubbleSort(&\$arr) : void
{

for (\$i = 0, \$c = count(\$arr); \$i < \$c; \$i++) {
\$swapped = false;
for (\$j = 0; \$j < \$c - \$i - 1; \$j++) {
if (\$arr[\$j + 1] < \$arr[\$j]) {
list(\$arr[\$j], \$arr[\$j + 1]) = array(\$arr[\$j + 1], \$arr[\$j]);
\$swapped = true;
}

if (!\$swapped) break; //没有发生交换，算法结束
}
}
}``````

``````procedure bubbleSort(A: list of sortable items)
n = length(A)
bound = n - 1
for i = 1 to n inclusive do
swapped = false
bound = 0
for j = 1 to bound inclusive do
if A[j] > A[j + 1] then
swap(A[j], A[j + 1])
swapped = true
newbound = j
end if
end for
bound = newbound
if swapped = false
break
endif
end for
end procedure
``````

``````function bubbleSort(&\$arr) : void
{
\$swapped = false;
\$bound = count(\$arr) - 1;
for (\$i = 0, \$c = count(\$arr); \$i < \$c; \$i++) {
for (\$j = 0; \$j < \$bound; \$j++) {
if (\$arr[\$j + 1] < \$arr[\$j]) {
list(\$arr[\$j], \$arr[\$j + 1]) = array(\$arr[\$j + 1], \$arr[\$j]);
\$swapped = true;
\$newBound = \$j;
}
}
\$bound = \$newBound;
if (!\$swapped) break; //没有发生交换，算法结束
}
}``````

### 选择排序

``````procedure  selectionSort( A : list of sortable items)
n = length(A)
for i = 1 to n inclusive do
min  =  i
for j = i + 1 to n inclusive do
if  A[j] < A[min] then
min = j
end if
end  for

if min != i
swap(a[i], a[min])
end if
end  for
end procedure``````

``````function selectionSort(&\$arr)
{
\$count = count(\$arr);

//重复元素个数-1次
for (\$j = 0; \$j <= \$count - 1; \$j++) {
//把第一个没有排过序的元素设置为最小值
\$min = \$arr[\$j];
//遍历每一个没有排过序的元素
for (\$i = \$j + 1; \$i < \$count; \$i++) {
//如果这个值小于最小值
if (\$arr[\$i] < \$min) {
//把这个元素设置为最小值
\$min = \$arr[\$i];
//把最小值的位置设置为这个元素的位置
\$minPos = \$i;
}
}
//内循环结束把最小值和没有排过序的元素交换
list(\$arr[\$j], \$arr[\$minPos]) = [\$min, \$arr[\$j]];
}

}``````

#### 选择排序的复杂度

best time complexity Ω(n2)
worst time complexity O(n2)
average time complexity Θ(n2)
space complexity (worst case) O(1)

### 插入排序

``````procedure insertionSort(A: list of sortable items)
n length(A)
for i=1 to n inclusive do
key = A[i]
j = i - 1
while j >= 0 and A[j] > key do
A[j+1] = A[j]
j--
end while
A[j + 1] = key
end for
end procedure``````

``````function insertionSort(array &\$arr)
{
\$len = count(\$arr);
for (\$i = 1; \$i < \$len; \$i++) {
\$key = \$arr[\$i];
\$j = \$i - 1;

while (\$j >= 0 && \$arr[\$j] > \$key) {
\$arr[\$j + 1] = \$arr[\$j];
\$j--;
}
\$arr[\$j + 1] = \$key;
}
}``````

#### 插入排序的复杂度

best time complexity Ω(n)
worst time complexity O(n2)
average time complexity Θ(n2)
space complexity (worst case) O(1)

### 归并排序

``````
/**
* 归并排序
* 核心：两个有序子序列的归并(function merge)
* 时间复杂度任何情况下都是 O(nlogn)
* 空间复杂度 O(n)
* 发明人: 约翰·冯·诺伊曼
* 速度仅次于快速排序，为稳定排序算法，一般用于对总体无序，但是各子项相对有序的数列
* 一般不用于内(内存)排序，一般用于外排序
*/

function mergeSort(\$arr)
{
\$lenght = count(\$arr);
if (\$lenght == 1) return \$arr;
\$mid = (int)(\$lenght / 2);

//把待排序数组分割成两半
\$left = mergeSort(array_slice(\$arr, 0, \$mid));
\$right = mergeSort(array_slice(\$arr, \$mid));

return merge(\$left, \$right);
}

function merge(array \$left, array \$right)
{
//初始化两个指针
\$leftIndex = \$rightIndex = 0;
\$leftLength = count(\$left);
\$rightLength = count(\$right);
//临时空间
\$combine = [];

//比较两个指针所在的元素
while (\$leftIndex < \$leftLength && \$rightIndex < \$rightLength) {
//如果左边的元素大于右边的元素，就将右边的元素放在单独的数组，并将右指针向后移动
if (\$left[\$leftIndex] > \$right[\$rightIndex]) {
\$combine[] = \$right[\$rightIndex];
\$rightIndex++;
} else {
//如果右边的元素大于左边的元素，就将左边的元素放在单独的数组，并将左指针向后移动
\$combine[] = \$left[\$leftIndex];
\$leftIndex++;
}
}

//右边的数组全部都放入到了返回的数组，然后把左边数组的值放入返回的数组
while (\$leftIndex < \$leftLength) {
\$combine[] = \$left[\$leftIndex];
\$leftIndex++;
}

//左边的数组全部都放入到了返回的数组，然后把右边数组的值放入返回的数组
while (\$rightIndex < \$rightLength) {
\$combine[] = \$right[\$rightIndex];
\$rightIndex++;
}

return \$combine;
}``````

#### 归并排序的复杂度

best time complexity Ω(nlogn)
worst time complexity O(nlogn)
average time complexity Θ(nlogn)
space complexity (worst case) O(n)

### 快速排序

``````function qSort(array &\$arr, int \$p, int \$r)
{
if (\$p < \$r) {
\$q = partition(\$arr, \$p, \$r);
qSort(\$arr, \$p, \$q);
qSort(\$arr, \$q + 1, \$r);
}
}

function partition(array &\$arr, int \$p, int \$r)
{
\$pivot = \$arr[\$p];
\$i = \$p - 1;
\$j = \$r + 1;

while (true) {
do {
\$i++;
} while (\$arr[\$i] < \$pivot);

do {
\$j--;
} while (\$arr[\$j] > \$pivot);

if (\$i < \$j) {
list(\$arr[\$i], \$arr[\$j]) = [\$arr[\$j], \$arr[\$i]];
} else {
return \$j;
}

}
}``````

#### 快速排序的复杂度

best time complexity Ω(nlogn)
worst time complexity O(n2)
average time complexity Θ(nlogn)
space complexity (worst case) O(logn)

### 桶排序

``````/**
* 桶排序
* 不是一种基于比较的排序
* T(N, M) = O(M + N) N是带排序的数据的个数，M是数据值的数量
* 当 M >> N 时，需要考虑使用基数排序
*/

function bucketSort(array &\$data)
{
\$bucketLen = max(\$data) - min(\$data) + 1;
\$bucket = array_fill(0, \$bucketLen, []);

for (\$i = 0; \$i < count(\$data); \$i++) {
array_push(\$bucket[\$data[\$i] - min(\$data)], \$data[\$i]);
}

\$k = 0;

for (\$i = 0; \$i < \$bucketLen; \$i++) {
\$currentBucketLen = count(\$bucket[\$i]);

for (\$j = 0; \$j < \$currentBucketLen; \$j++) {
\$data[\$k] = \$bucket[\$i][\$j];
\$k++;
}
}
}``````

#### 快速排序的复杂度

best time complexity Ω(n+k)
worst time complexity O(n2)
average time complexity Θ(n+k)
space complexity (worst case) O(n)

### PHP内置的排序算法

PHP有丰富的预定义函数库，也包含不同的排序函数。它有不同的功能来排序数组中的项目，你可以选择按值还是按键/索引进行排序。在排序时，我们还可以保持数组值与它们各自的键的关联。下面是这些函数的总结

sort() 升序排列数组。value/key关联不保留
rsort() 按反向/降序排序数组。index/key关联不保留
asort() 在保持索引关联的同时排序数组
arsort() 对数组进行反向排序并维护索引关联
ksort() 按关键字排序数组。它保持数据相关性的关键。这对于关联数组是有用的
krsort() 按顺序对数组按键排序
natsort() 使用自然顺序算法对数组进行排序，并保持value/key关联
natcasesort() 使用不区分大小写的“自然顺序”算法对数组进行排序，并保持value/key关联。
usort() 使用用户定义的比较函数按值对数组进行排序，并且不维护value/key关联。第二个参数是用于比较的可调用函数
uksort() 使用用户定义的比较函数按键对数组进行排序，并且不维护value/key关联。第二个参数是用于比较的可调用函数
uasort() 使用用户定义的比较函数按值对数组进行排序，并且维护value/key关联。第二个参数是用于比较的可调用函数

• SORT_REGULAR - 正常比较单元（不改变类型）
• SORT_NUMERIC - 单元被作为数字来比较
• SORT_STRING - 单元被作为字符串来比较
• SORT_LOCALE_STRING - 根据当前的区域（locale）设置来把单元当作字符串比较，可以用 setlocale() 来改变。
• SORT_NATURAL - 和 natsort() 类似对每个单元以“自然的顺序”对字符串进行排序。 PHP 5.4.0 中新增的。
• SORT_FLAG_CASE - 能够与 SORT_STRING 或 SORT_NATURAL 合并（OR 位运算），不区分大小写排序字符串。

### 完整内容

#### 你可能感兴趣的

2 条评论

``````public function bucketSort(array &\$arr)
{
\$bucket_length = max(\$arr) - min(\$arr) + 1;
\$bucket = array_fill(min(\$arr), \$bucket_length, 0);
foreach (\$arr as \$key => \$value)
{
\$bucket[\$value] ++;
}
\$arr = [];
foreach (\$bucket as \$key => \$value)
{
if (!empty(\$value))
{
for (\$i = 0; \$i < \$value; \$i++)
{
\$arr[] = \$key;
}
}
}
return \$arr;
}``````

Kwokfu · 3月29日

function selectionSort(\$arr)
{

``````\$count = count(\$arr);

//重复元素个数-1次
for (\$j = 0; \$j <= \$count - 1; \$j++) {
//把第一个没有排过序的元素设置为最小值
\$min = \$arr[\$j];
//遍历每一个没有排过序的元素
for (\$i = \$j + 1; \$i < \$count; \$i++) {
//如果这个值小于最小值
if (\$arr[\$i] < \$min) {
//把这个元素设置为最小值
\$min = \$arr[\$i];
//把最小值的位置设置为这个元素的位置
\$minPos = \$i;
}
}

if (isset(\$minPos) && !empty(\$minPos)) {
//内循环结束把最小值和没有排过序的元素交换
list(\$arr[\$j], \$arr[\$minPos]) = [\$min, \$arr[\$j]];
}

unset(\$minPos);
}``````

}