欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

常用排序算法

程序员文章站 2022-04-24 09:57:47
冒泡排序 两数相较,大的数下沉,小的数上升。 选择排序 在长度为N的数组中,找到后面N-1个数中的最小值与第1个数字交换,后N-2中最小值与第2个交换,以此类推直至最后一个数。 插入排序 假设数组中前n-1是已排好序,将第n个数插入到前面使这n个数也是排好序的,如此从第一个数开始循环直至全部排好序。 ......
  • 冒泡排序

两数相较,大的数下沉,小的数上升。

function bubbleSort(array $arr)
{
    for ($i=0, $len=count($arr); $i < $len; $i++) { 
        $flag = false;
        for ($j=0; $j < $len-1; $j++) { 
            if ($arr[$j] > $arr[$j+1]) {
                $tmp = $arr[$j];
                $arr[$j] = $arr[$j+1];
                $arr[$j+1] = $tmp;
                $flag = true;
            }
        }
        // 若没有交换发生,提前终止;
        if ($flag == false) break;
    }
    return $arr;
}
  • 选择排序

在长度为N的数组中,找到后面N-1个数中的最小值与第1个数字交换,后N-2中最小值与第2个交换,以此类推直至最后一个数。

function selectSort(array $arr)
{
    for ($i=0, $len=count($arr); $i < $len-1; $i++) { 
        $min_key = $i+1;
        for ($j=$i+1; $j < $len; $j++) { 
            if ($arr[$j] < $arr[$min_key]) {
                $min_key = $j;
            }
        }
        if ($arr[$i] > $arr[$min_key]) {
            $tmp = $arr[$i];
            $arr[$i] = $arr[$min_key];
            $arr[$min_key] = $tmp;
        }
    }
    return $arr;
}

 

  • 插入排序

假设数组中前n-1是已排好序,将第n个数插入到前面使这n个数也是排好序的,如此从第一个数开始循环直至全部排好序。

function insertSort(array $arr)
{
    for ($i=0, $len=count($arr); $i < $len-1; $i++) {
        for ($j=$i+1; $j > 0; $j--) { 
            // 若后面的数比前面的小,则发生交换
            if ($arr[$j] < $arr[$j-1]) {
                $tmp = $arr[$j];
                $arr[$j] = $arr[$j-1];
                $arr[$j-1] = $tmp;
            }
        }
    }
    return $arr;
}

 

  • 希尔排序

可以看做是一种分组插入排序,将数组按照某个增量进行排序,再将增量逐步减小,直至增量为1

function shellSort(array $arr)
{
    $len = count($arr);
    $inc = round($len / 2);
    while (true) { 
        for ($i=0; $i < $inc; $i++) { 
            for ($j=$i+$inc; $j < $len; $j+=$inc) { 
                for ($k=$j-$inc; $k >= $i; $k-=$inc) { 
                    if ($arr[$k] > $arr[$k+$inc]) {
                        $tmp = $arr[$k];
                        $arr[$k] = $arr[$k+$inc];
                        $arr[$k+$inc] = $tmp;
                    }
                }
            }
        }
        if ($inc == 1) break;
        $inc = round($inc / 2);
    }
    return $arr;
}

 

  • 快速排序

先从数组中选取1个数作为key值,将比key小的放在左边,大的放在右边。使用递归对key两端的数列作同样的操作。

function quickSort(array $arr, $left = null, $right = null)
{
    $left = $left===null ? 0 : $left;
    $right = $right===null ? count($arr)-1 : $right;
    if ($left >= $right) {
        return $arr;
    }
    $key = $arr[$left]; $i = $left; $j = $right;
    while ($i < $j) {
        while ($i < $j && $arr[$j] >= $key) {
            $j--;
        }
        if ($i < $j) {
            $arr[$i] = $arr[$j];
            $i++;
        }
        while ($i < $j && $arr[$i] < $key) {
            $i++;
        }
        if ($i < $j) {
            $arr[$j] = $arr[$i];
            $j--;
        }
    }
    $arr[$i] = $key;
    $arr = quickSort($arr, $left, $i-1);
    $arr = quickSort($arr, $i+1, $right);
    return $arr;
}

 

  • 归并排序

有序数组的合并,将数列分解为最小单元,然后依次合并。

function mergeSort(array $arr)
{
    $merge = $arr;
    while (true) {
        $tmp = []; 
        $count = count($merge);
        if ($count == 1) {
            return $merge[0];
        }
        for ($i=0; $i < $count; $i+=2) { 
            if (isset($merge[$i+1])) {
                $tmp[] = arrayMerge($merge[$i], $merge[$i+1]);
            } else {
                $tmp[] = $merge[$i];
            }
        }
        $merge = $tmp;
    }
}
function arrayMerge($a, $b)
{
    if (!is_array($a) && !is_array($b)) {
        if ($a < $b) 
            return [$a, $b];
        else
            return [$b, $a];
    } else {
        $c = [];
        $i = $j = $k = 0;
        $m = count($a);
        $n = count($b);
        while ($i<$m && $j<$n) {
            if($a[$i] < $b[$j]) 
                $c[$k++] = $a[$i++];
            else
                $c[$k++] = $b[$j++];
        }
        while ($i < $m) {
            $c[$k++] = $a[$i++];
        }
        while ($j < $n) {
            $c[$k++] = $b[$j++];
        }
        return $c;
    }
}

 

  • 堆排序

 堆是一种完全二叉树,分为大根堆和小根堆,大根堆要求每个节点的值不大于父节点的值,小根堆反之。堆排序就是利用这种数据结构设计的一种排序算法,它是选择排序的一种,可以利用数组的特点快速定位索引所在的元素。

function heapSort(array $arr)
{
    $len = count($arr);
    for ($i=$len-1; $i >= 0; $i--) { 
        $arr = buildHeap($arr, $len, $i);
        $arr = swap($arr, 0, $i);
    }
    return $arr;
}
// 建立堆,顺序逆序分拣建立大根堆小根堆
function buildHeap($arr, $len, $lmt)
{
    for ($i=intval($len/2)-1; $i >= 0; $i--) { 
        $left = 2*$i+1;
        $right = 2*$i+2;
        if ($left > $lmt) continue;
        if ($right > $lmt) {
            $k = $left;
        } else {
            $k = $arr[$left]>$arr[$right] ? $left : $right;
        }
        if ($arr[$i] < $arr[$k]) {
            $arr = swap($arr, $i, $k);
        }
    }
    return $arr;
}
// 交换数据
function swap($arr, $k1, $k2)
{
    $tmp = $arr[$k1];
    $arr[$k1] = $arr[$k2];
    $arr[$k2] = $tmp;
    return $arr;
}

 

  • 基数排序

binSort将值作为键值放入对应的位置,然后直接遍历数组得到结果。当序列中存在较大值时,BinSort 的排序方法会浪费大量的空间开销。基数排序是在BinSort的基础上,通过基数的限制来减少空间的开销。基数排序的过程是将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。

function radixSort(array $arr, $level=1)
{
    // 采用LSD
    $limit = pow(10, $level);
    $div = pow(10, $level-1);
    $flag = false;
    $bucket = [];
    $ret = [];
    foreach ($arr as $v) {
        $bucket[intval($v/$div)%10][] = $v;
        if ($v >= $limit) $flag = true;
    }
    for ($i=0; $i < 10; $i++) { 
        if (isset($bucket[$i])) {
            $ret = array_merge($ret, $bucket[$i]);
        }
    }
    if ($flag) {
        $ret = radixSort($ret, $level+1);
    }
    return $ret;
}