Arr::heapSort()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 15
ccs 9
cts 9
cp 1
rs 10
c 0
b 0
f 0
cc 3
nc 4
nop 1
crap 3
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: yiranzai
5
 * Date: 19-3-22
6
 * Time: 上午11:21
7
 */
8
9
namespace Yiranzai\Tools;
10
11
use Exception;
12
13
/**
14
 * Class Arr
15
 * @package Yiranzai\Tools
16
 */
17
class Arr
18
{
19
    /**
20
     * 使用给定的回调对数组进行排序并保留原始键。
21
     * @param array    $array
22
     * @param callable $callback
23
     * @param int      $options
24
     * @param bool     $descending
25
     * @return array
26
     */
27 3
    public static function sortBy(array $array, callable $callback, $options = SORT_REGULAR, $descending = false): array
28
    {
29 3
        $results = [];
30
31 3
        foreach ($array as $key => $value) {
32 3
            $results[$key] = $callback($value, $key);
33
        }
34
35 3
        $descending ? arsort($results, $options)
36 3
            : asort($results, $options);
37
38 3
        foreach (array_keys($results) as $key) {
39 3
            $results[$key] = $array[$key];
40
        }
41
42 3
        return $results;
43
    }
44
45
    /**
46
     * 二维数组按照某个字段排序
47
     * @param array $arr   要排序的数组
48
     * @param mixed $field 要排序的字段
49
     * @param int   $arg   排序规则
50
     * @return array
51
     */
52 3
    public static function arrSortByField(array $arr, $field, $arg = SORT_ASC): array
53
    {
54 3
        if (!empty($arr)) {
55 3
            foreach ($arr as $v) {
56 3
                $sort[] = $v[$field];
57
            }
58 3
            array_multisort($sort, $arg, $arr);
59
        }
60 3
        return $arr;
61
    }
62
63
    /**
64
     * 数组group by
65
     * @param array  $arr
66
     * @param string $field
67
     * @param bool   $unique
68
     * @return array
69
     * @throws Exception
70
     */
71 3
    public static function arrGroup(array $arr, string $field, $unique = false): array
72
    {
73 3
        $group = [];
74 3
        foreach ($arr as $item) {
75 3
            $groupField = is_array($item) ? Tools::arrGet($item, $field) : Tools::objectGet($item, $field);
76 3
            if (empty($groupField) && 0 !== $groupField) {
77
                continue;
78
            }
79
            //  只取其中一个
80 3
            if ($unique) {
81 3
                $group[$groupField] = $item;
82
            } else {
83 3
                $group[$groupField][] = $item;
84
            }
85
        }
86 3
        return $group;
87
    }
88
89
    /**
90
     * @param array $array
91
     * @return array
92
     */
93 3
    public static function heapSort(array $array = []): array
94
    {
95 3
        $len     = count($array);
96 3
        $lastKey = ($len - 1) >> 1;
97
        //构建一个大顶堆
98 3
        for ($i = $lastKey; $i >= 0; $i--) {
99 3
            self::maxHeapify($array, $i, $len);
100
        }
101 3
        for ($i = $len - 1; $i > 0; $i--) {
102
            //将构建好的大顶堆的顶点与最后一个没排序的点交换
103 3
            self::swap($array[0], $array[$i]);
104
            //将剩下的没排序的数据重新构建为一个大顶堆
105 3
            self::maxHeapify($array, 0, $i);
106
        }
107 3
        return $array;
108
    }
109
110
    /**
111
     * @param array $arr
112
     * @param int   $start
113
     * @param int   $end
114
     */
115 3
    private static function maxHeapify(&$arr, $start, $end): void
116
    {
117 3
        $son = $start * 2 + 1;
118 3
        if ($son >= $end) {
119 3
            return;
120
        }
121 3
        if ($son + 1 < $end && $arr[$son] < $arr[$son + 1]) {
122 3
            $son++;
123
        }
124 3
        if ($arr[$start] <= $arr[$son]) {
125 3
            self::swap($arr[$start], $arr[$son]);
126 3
            self::maxHeapify($arr, $son, $end);
127
        }
128 3
    }
129
130
    /**
131
     * @param mixed $a
132
     * @param mixed $b
133
     */
134 3
    private static function swap(&$a, &$b): void
135
    {
136 3
        $t = $a;
137 3
        $a = $b;
138 3
        $b = $t;
139 3
    }
140
141
    /**
142
     * 不断均分为左右两个数组,然后取出两个数组每个相同位置的值,比较大小,并push到队列中,最后按照 队列,左数组,右数组的顺序来合并
143
     * 从最小单元开始排序合并,然后返回到上一个大小的单元进行排序合并
144
     *
145
     * @param array $array
146
     * @return array
147
     */
148 3
    public static function mergeSort(array $array): array
149
    {
150 3
        $len = count($array);
151 3
        if ($len <= 1) {
152 3
            return $array;
153
        }
154
        //如果数组长度为奇数,则$m需要等于长度的一半向上补齐整数,偶数则需要等于一半,只有这样array_chunk才能恰好分割为两个长度几乎相同的数组
155 3
        $m = ($len + 1) >> 1;
156 3
        [$left, $right] = array_chunk($array, $m);
157 3
        $left  = self::mergeSort($left);
158 3
        $right = self::mergeSort($right);
159 3
        $reg   = [];
160 3
        while (count($left) && count($right)) {
161 3
            if ($left[0] < $right[0]) {
162 3
                $reg[] = array_shift($left);
163
            } else {
164 3
                $reg[] = array_shift($right);
165
            }
166
        }
167 3
        return array_merge($reg, $left, $right);
168
    }
169
170
    /**
171
     * 每次都取中间的那个数,遍历数组,比它大放右边,比它小放左边
172
     *
173
     * @param array $array
174
     * @return array
175
     */
176 3
    public static function quickSort(array $array): array
177
    {
178 3
        $len = count($array);
179 3
        if ($len <= 1) {
180 3
            return $array;
181
        }
182 3
        $m      = $len >> 1;
183 3
        $mValue = $array[$m];
184 3
        $left   = $right = [];
185 3
        foreach ($array as $key => $iValue) {
186 3
            if ($key === $m) {
187 3
                continue;
188
            }
189 3
            if ($iValue < $mValue) {
190 3
                $left[] = $iValue;
191
            } else {
192 3
                $right[] = $iValue;
193
            }
194
        }
195 3
        return array_merge(self::quickSort($left), [$mValue], self::quickSort($right));
196
    }
197
}
198