【PHP常用四种排序算法】

1、冒泡排序

思想:两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。

时间复杂度:该算法的时间复杂度为O(n2)。但是,当原始关键字序列已有序时,只进行一趟比较就结束,此时时间复杂度为O(n)。

实现代码:

<?php

//冒泡排序(一维数组)
function bubble_sort($array)
{
    $count = count($array);
    if ($count <= 0) return false;
    for ($i = 0; $i < $count - 1; $i++) {
        for ($j = 0; $j < $count - $i - 1; $j++) {
            if ($array[$j] > $array[$j + 1]) {
                $temp = $array[$j];
                $array[$j] = $array[$j + 1];
                $array[$j + 1] = $temp;
            }
        }
    }
    return $array;
}

$arr = array(2, 1, 3, 6, 5, 4, 8, 7, 9, 15, 12, 16);
print_r(bubble_sort($arr));
View Code

2、选择排序

思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换。然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

时间复杂度:时间复杂度为o(n^2),不稳定排序,适合规模比较小的

实现代码

<?php

//选择排序(一维数组)
function select_sort($array)
{
    //外层控制轮数,内层控制比较次数
    $count = count($array);
    for ($i = 0; $i < $count - 1; $i++) {
        //假设最小值的位置
        $pos = $i;
        for ($j = $i + 1; $j < $count; $j++) {
            //最小值与当前值比较
            if ($array[$pos] > $array[$j]) {
                //比较,发现更小的,记录下最小值的位置;并且在下次比较时采用已知的最小值进行比较。
                $pos = $j;
            }
        }
        //已经确定了当前的最小值的位置,保存到$pos中。如果发现最小值的位置与当前假设的位置$i不同,则位置互换即可。
        if ($pos != $i) {
            $temp = $array[$pos];
            $array[$pos] = $array[$i];
            $array[$i] = $temp;
        }
    }
    return $array;
}

$arr = array(23, 5, 26, 4, 9, 85, 21, 39, 55, 88, 421, 226);
print_r(select_sort($arr));
View Code

3、插入排序

思想:在要排序的一组数中,假设前面的数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

时间复杂度:如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上(n-1)次。平均来说插入排序算法的时间复杂度为O(n^2)。因而,插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择。

实现代码:

<?php

//插入排序(一位数组)
function insert_sort($array)
{
    $count = count($array);
    for ($i = 1; $i < $count; $i++) {
        $temp = $array[$i];
        //内层循环,比较并插入
        for ($j = $i - 1; $j >= 0; $j--) {
            //发现插入的元素要小,交换位置,将后边的元素与前面的元素互换
            if ($temp < $array[$j]) {
                $array[$j + 1] = $array[$j];
                $array[$j] = $temp;
            } else {
                //如果碰到不需要移动的元素,由于是已经排序好是数组,则前面的就不需要再次比较了。
                break;
            }
        }
    }
    return $array;
}

$arr = array(23, 5, 26, 4, 9, 85, 21, 39, 55, 88, 421, 226);
print_r(insert_sort($arr));
View Code

4、快速排序

思想:选择一个基准元素,通常选择第一个元素或者最后一个元素。通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素。此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

时间复杂度:快速排序主体算法时间运算量约 O(log2n) ,划分子区函数运算量约 O(n) ,所以总的时间复杂度为 O(nlog2n) ,它显然优于冒泡排序 O(n2). 可是算法的优势并不是绝对的。试分析,当原文件关键字有序时,快速排序时间复杂度是O(n2), 这种情况下快速排序不快。而这种情况的冒泡排序是 O(n), 反而很快。在原文件记录关键字无序时的多种排序方法中,快速排序被认为是最好的一种排序方法。

实现代码

<?php

//快速排序(一位数组)
function quick_sort($array)
{
    $count = count($array);
    if ($count <= 1) return $array;
    //选择第一个元素作为基准
    $base_num = $array[0];
    //遍历除了标尺外的所有元素,按照大小关系放入两个数组内
    $left_array = array();    //小于基准的
    $right_array = array();   //大于基准的
    for ($i = 1; $i < $count; $i++) {
        if ($base_num > $array[$i]) {
            //放入左边数组
            $left_array[] = $array[$i];
        } else {
            //放入右边
            $right_array[] = $array[$i];
        }
    }
    //再分别对左边和右边的数组进行相同的排序处理方式递归调用这个函数
    $left_array = quick_sort($left_array);
    $right_array = quick_sort($right_array);
    //合并数组
    return array_merge($left_array, array($base_num), $right_array);
}

$arr = array(23, 5, 26, 4, 9, 85, 21, 39, 55, 88, 421, 226);
print_r(quick_sort($arr));
View Code

几种排序算法的比较和选择 

1. 选取排序方法需要考虑的因素:

1)待排序的元素数目n;

2) 元素本身信息量的大小;

3)关键字的结构及其分布情况;

4) 语言工具的条件,辅助空间的大小等。

2. 小结:

(1) 若n较小(n <= 50),则可以采用直接插入排序或直接选择排序。由于直接插入排序所需的记录移动操作较直接选择排序多,因而当记录本身信息量较大时,用直接选择排序较好。

(2) 若文件的初始状态已按关键字基本有序,则选用直接插入或冒泡排序为宜。

(3) 若n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序。 快速排序是目前基于比较的内部排序法中被认为是最好的方法。

(4) 在基于比较排序方法中,每次比较两个关键字的大小之后,仅仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程,由此可以证明:当文件的n个关键字随机分布时,任何借助于"比较"的排序算法,至少需要O(nlog2n)的时间。

(5) 当记录本身信息量较大时,为避免耗费大量时间移动记录,可以用链表作为存储结构。

 

posted on 2015-07-06 15:50  gimin  阅读(269)  评论(0)    收藏  举报