zoukankan      html  css  js  c++  java
  • PHP 查找随即数组中的最小的k个数

      1 <?php
      2     #查找数组中最小的k个数
      3     
      4     function swap(&$arr, $i, $j) {
      5         $temp = $arr[$i];
      6         $arr[$i] = $arr[$j];
      7         $arr[$j] = $temp;
      8     }
      9 
     10     #第一种方法,使用选择排序直到排好序的部分元素个数为k,效率为O(kn)
     11     function select_sort_k($arr, $k) {
     12         if ($k >= count($arr)) {
     13             return $arr;
     14         }
     15         for ($i = 0; $i < count($arr); $i++) {
     16             $min = $i;
     17             for ($j = $i; $j < count($arr); $j++) {
     18                 if ($arr[$j] < $arr[$min]) {
     19                     $min = $j;
     20                 }
     21             }
     22 
     23             swap($arr, $i, $min);
     24 
     25             if ($i == $k - 1) {
     26                 return array_slice($arr, 0, $k);
     27             }
     28         }
     29     }
     30 
     31     #第二种方法,通过建立最小堆,然后弹出最小元素来实现,效率为O(klogn)
     32 
     33     #调整堆节点
     34     #@param a 待调整数组
     35     #@param start 待调整部分开始坐标
     36     #@param len 待调整数组的长度
     37     function min_heapify(&$a, $start, $len) {
     38         $min = $start;
     39         $left = ($start + 1) * 2 - 1; #左孩子坐标
     40         $right = $left + 1; #右孩子坐标
     41 
     42         if ($left < $len) {
     43             if ($a[$min] > $a[$left]) {
     44                 $min = $left;
     45             }
     46         }
     47 
     48         if ($right < $len) {
     49             if ($a[$min] > $a[$right]) {
     50                 $min = $right;
     51             }
     52         }
     53 
     54         #递归调整节点
     55         if ($min != $start) {
     56             swap($a, $min, $start);
     57             min_heapify($a, $min, $len);
     58         }
     59     }
     60 
     61     #建立最小堆
     62     function build_min_heap(&$a) {
     63         #从最后一个非叶子节点开始调整堆
     64         for ($i = floor(count($a) / 2) - 1; $i >= 0; $i--) {
     65             min_heapify($a, $i, count($a));
     66         }
     67     }
     68 
     69     #利用类似于堆排序的过程查找最小的k个元素
     70     function heap_min_k(&$a, $k) {
     71         build_min_heap($a);
     72         for ($i = 0; $i < $k; $i++) {
     73             #交换首尾元素,并重新调整堆
     74             swap($a, 0, count($a) - 1);
     75             $r[] = array_pop($a);
     76             min_heapify($a, 0, count($a));
     77         }
     78         return $r;
     79     }
     80 
     81     #第三种方法,利用快排的partition来查找
     82     function rand_partition(&$a, $start, $end) {
     83         swap($a, $start, rand($start, $end));
     84         return partition($a, $start, $end);
     85     }
     86 
     87     function partition(&$a, $start, $end) {
     88         $pivot = $start;
     89         $low = $start + 1;
     90         $high = $end;
     91         while ($low < $high) {
     92             while ($low < $high && $a[$low] <= $a[$pivot]) {
     93                 $low++;
     94             }
     95 
     96             #这里表示把所有与pivot相等的元素放到左边
     97             while ($low < $high && $a[$high] > $a[$pivot]) {
     98                 $high--;
     99             }
    100 
    101             swap($a, $low, $high);
    102         }
    103 
    104         $change = $low;
    105         if ($a[$pivot] < $a[$change]) {
    106             $change--;
    107         }
    108         swap($a, $change, $pivot);
    109         return $change;
    110     }
    111 
    112     #利用类似于快排的性质来查找k个最小的元素
    113     function qsort_k(&$a, $start, $end, &$result, $k) {
    114         $q = rand_partition($a, $start, $end);
    115         $n = $q - $start + 1; #n表示包括q,小于等于q的元素的总数
    116 
    117         if ($n == $k) { #如果n = k,说明左边的元素正好足够,全部加入结果集
    118             array_splice($result, count($result), 0, array_slice($a, $start, $n));
    119         } else if ($n < $k) { #如果n < k, 说明左边的元素不够k个,将左边的元素和q一起归入结果集,并进入递归
    120             array_splice($result, count($result), 0, array_slice($a, $start, $n));
    121             qsort_k($a, $q + 1, $end, $result, $k - $n);
    122         } else {
    123             #元素有多,进入左边继续递归
    124             qsort_k($a, $start, $q - 1, $result, $k);
    125         }
    126     }
    127 
    128     $a = array(5, 7, 3, 2, 4, 6, 9, 0, 1);
    129     print_r($a);
    130     echo "<br>";
    131     print_r(select_sort_k($a, 5));
    132     echo "<br>";
    133     echo "<br>";
    134 
    135     $a = array(5, 7, 3, 2, 4, 6, 9, 0, 1);
    136     print_r($a);
    137     echo "<br>";
    138     print_r(heap_min_k($a, 5));
    139     echo "<br>";
    140     echo "<br>";
    141 
    142     $a = array(5, 7, 3, 2, 4, 6, 9, 0, 1);
    143     print_r($a);
    144     echo "<br>";
    145     $r = array();
    146     qsort_k($a, 0, count($a) - 1, $r, 5);
    147     print_r($r);
    148 ?>

    Array ( [0] => 5 [1] => 7 [2] => 3 [3] => 2 [4] => 4 [5] => 6 [6] => 9 [7] => 0 [8] => 1 ) 
    Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 ) 

    Array ( [0] => 5 [1] => 7 [2] => 3 [3] => 2 [4] => 4 [5] => 6 [6] => 9 [7] => 0 [8] => 1 ) 
    Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 ) 

    Array ( [0] => 5 [1] => 7 [2] => 3 [3] => 2 [4] => 4 [5] => 6 [6] => 9 [7] => 0 [8] => 1 ) 
    Array ( [0] => 0 [1] => 1 [2] => 3 [3] => 2 [4] => 4 )

  • 相关阅读:
    BootStrap2学习日记15----选项卡
    BootStrap2学习日记14----导航
    Google地图下载工具代码
    SqlServer 动态SQL(存储过程)中Like 传入参数无正确返回值的问题
    地球坐标-火星坐标-百度坐标及之间的转换算法 C#
    GIS基础知识
    Gps坐标有效性判定
    Gps坐标距离计算C#实现
    C# 对字段忽略模型校验
    SQL基础复习2
  • 原文地址:https://www.cnblogs.com/zemliu/p/2706475.html
Copyright © 2011-2022 走看看