排序算法


十大排序算法:参考链接


1. 冒泡排序

重复地走访过要排序的数列,一次比较两个元素。如果第一个比第二个大,顺序调换

这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

image

$arr = [2, 10, 7, 20, 44, 38, 100, 1, 20];
$count = count($arr);

for ( $i=0; $i<$count-1; $i++) {
    for ($j=0; $j<$count-1-$i; $j++) {  // 设置次数
    
        if ($arr[$j] > $arr[$j+1]) {  // 前者和或者比较
            $temp = $arr[$j];  // 交换值
            $arr[$j] = $arr[$j+1];
            $arr[$j+1] = $temp;
        }
        
    }
}


2. 选择排序

比较序列中最小的值,记录键值,排列到起始位置。

image

$arr = [5, 44, 89, 10, 2, 63, 9, 1, 20];
$count = count($arr);

for ($i=0; $i<$count-1; $i++) {
    $minIndex = $i;  // 初始key值
    for ($j=$i+1; $j<$count; $j++) {  // 用初始值,循环比较
        if ($arr[$j] < $arr[$minIndex]) {
            $minIndex = $j;  // 较小的重新赋值
        }
    }
    
    $temp = $arr[$i];  // 位置切换
    $arr[$i] = $arr[$minIndex];
    $arr[$minIndex] = $temp;
}


3. 插入排序

根据当前key值判断是否大于下一个value值,后进行替换

image

$arr = [9, 20, 80, 2, 6, 40, 1, 5];
$count = count($arr);

for ($i=1; $i<$count; $i++) {
    $preIndex = $i-1;  // key 值 0
    $current = $arr[$i]; // value 值 20
    
    while ($preIndex>=0 && $arr[$preIndex] > $current) {  // 如果 9 > 20 并且 key >= 0,则替换
        $arr[$preIndex+1] = $arr[$preIndex];  // 替换值
        $preIndex --;
    }

    $arr[$preIndex+1] = $current;  // -1+1=0;
}


4. 希尔排序

是直接插入排序算法的一种更高效的改进版本,又称“缩小增量排序”

将要排序的数组按下标的一定增量进行分组,每组进行插入排序,随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个数组都被分成一组,算法结束。

$arr = [3,9,2,5,7,6,8,1];
$count = count($arr);

for ($gap = $count/2; $gap>0; $gap=$gap/2) {   // 设置增量数 421
    
    for ($i=$gap; $i<$count; $i++ ) {  // 根据增量数进行循环
        $j = $i
        while ($j-$gap>=0 && $arr[$j]<$arr[$j-$gap]) {  // 根据增量进行前后判断
            
            $temp = $arr[$j];  // 位置切换
            $arr[$j] = $arr[$j-$gap];
            $arr[$j-$gap] = $temp;
            $j -= $gap;
        }
    }
}



5. 快速排序

设置一个初始的中间值,来将需要排序的数组分成3部分。

小于中间值的放左边,中间值,大于中间值的放右边。使用递归用相同的方式来排序左边和右边,最后合并数组。

image

$arr = [3,9,2,5,7,6,8,1];

function quickSort($arr) {
    $count = count($arr);
    if($count>2) {
        return $arr;
    }
    $leftArr = [];   // 设置左右值
    $rightArr = [];
    $middle = $arr[0];  // 基准值,小->左边,大->右边
    
    for ($i=1; $i<$count; $i++) {  // 循环比较基准值
        if ($midder < $arr[$i]) {
            $rightArr[] = $arr[$i];
        }else{
            $leftArr[] = $arr[$i];
        }
    }
    
    $rightArr = quickSort($rightArr);  // 递归排序
    $leftArr = quickSort($leftArr);
    
    return array_merage($rightArr, $middle, $leftArr);
}


6. 计数排序

统计数组中每个元素出现的次数,对所有的计数累加

$arr = [3, 9, 2, 5, 7, 6, 8, 1, 1, 2, 5];

$maxValue = max($arr);


for ($m = 0; $m < $maxValue + 1; $m++) {
    $bucket[] = null;   // 设置空数组值
}

$arrLen = count($arr);

for ($i = 0; $i < $arrLen; $i++) {
    if (!array_key_exists($arr[$i], $bucket)) {
        $bucket[$arr[$i]] = 0;
    }
    $bucket[$arr[$i]]++;
}

$sortedIndex = 0;
foreach ($bucket as $key => $len) {
    if ($len !== null) $arr[$sortedIndex++] = $key;
    if($len !== null){
        for($j = 0; $j < $len; $j++){
            $arr[$sortedIndex++] = $key;
        }
    }
}


7. 二分查找

也称折半查找,它是一种效率较高的查找方法。

就是一分为二,然后两边比较,保留有效区间,继续一分为二查找,直到找到或者超出区间则结束

必须采用顺序存储结构,必须按关键字大小有序排列


设置 low = 0 、hight=10、mid=(low+hight) / 2 = 5,target = 52

比较中间元素 mid 和目标元素 target,如48小于52,则low=mid+1 = 6

此时 low = 6,hight = 10,min = 8

如没有相等,继续比较。69大于52,则high=mid-1 = 7

此时 low = 6,hight = 7,min = 6

///////////////////////////////////////////////////////////////
// 循环方式
function binary_search ($arr, $number) {
    if (!in_array($arr, $number) || empty($number)) {
        return '';
    }
    
    $count = count($arr);
    $lower = 0;   // 最小key
    $hight = $count-1;  // 最大key
    
    whlie ($lower<=$hight) {
        $middle = (($lower + $hight) / 2);  // 中间key
        
        if ($arr[$middle] < $number) {  // 中间值与查找树比较,查找树大舍去左边。查找树小舍去右边
            $lower = $middle + 1;
        }else if($arr[$middle] > $number) {
            $hight = $middle -1;
        }else{
            return $middle;
        }
        
    }
    return '';
}

$arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$find_key = binary_search($arr, 7);

///////////////////////////////////////////////////////////////
// 递归方式
function binary_search_recursion($arr, $number, $lower, $higher) {
    if ($lower > $higher) {
        return -1;
    }
    $middle = intval(($lower+$higher) /2);
    if ($number > $arr[$middle]) {
        // 查找数比参照点大,舍去左边继续查找
        return binary_search_recursion($arr, $number, $middle+1, $higher);
    } elseif ($number < $arr[$middle]) {
        return binary_search_recursion($arr, $number, $lower, $middle-1);
    } else {
        return $middle;
    }
}
$arr = [1, 3, 7, 9, 11, 57, 63, 99];
binary_search_recursion($arr,11,0,count($arr));


8. 桶排序

桶排序是计数排序的升级版。它利用了函数的映射关系

在额外空间充足的情况下,尽量增大桶的数量

使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中

image

$arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

$min = min($arr);
$max = max($arr);

$bucket = array_fill($min, $max-$min+1, 0);  // 生成桶,默认每个桶中数据只有0个
 
foreach ($nonSortArray as $value){
    $bucket[$value]++;  // 对应桶的个数计增
}

$sortArray = [];  
foreach ($bucket as $k=>$v) {
    for ($i=1; $i<=$v; $i++) {  // 每个桶中的个数
        $sortArray[]=$k;
    }
}
return $sortArray;


9. 基数排序

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较

由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数

image

$arr = [3, 9, 2, 5, 7, 6, 8, 1, 4, 90];


$arr_len = count($arr);

if ($arr_len<=1) {
    return $arr;
}

$max = max($arr);
$max_len = strlen($max);	// 获取最大的数的位数

$radix = 1; // 基数,从最后一位数开始
for ($i=0; $i < $max_len; $i++) { // 按最大位数读取各位的数
    for ($j=0; $j < 10; $j++) {
        $buckets[$j]=[]; // 用来装不同基数对应的值
    }

    foreach ($arr as $val) { // 按基数把数放到桶里
        $buckets[($val/$radix)%10][]=$val;
    }

    $radix *= 10; // 基数进位

    $k = 0;
    $arr = [];
    foreach ($buckets as $bucket) { // 把桶里的数重新存起来
        foreach ($bucket as $val) {
            $arr[$k++] = $val;
        }
    }
}
posted @   linsonga  阅读(49)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示