Resident234
@Resident234
Back-End . PHP . Bitrix

PHP. Как отсортировать SplFixedArray?

Доброго дня.
Есть ли примеры кода, который сортирует массив типа SplFixedArray ?
  • Вопрос задан
  • 237 просмотров
Пригласить эксперта
Ответы на вопрос 1
Resident234
@Resident234 Автор вопроса
Back-End . PHP . Bitrix
Отвечаю на свой же вопрос

class SortableSplFixedArray extends SplFixedArray {
    /**
     * Take an array and build an instance of the current class around it. No need 
     * to overwrite this for children.
     * @static
     * @param array $array
     * @return array
     */
    public static function fromArray(array $array) {
        $class = __CLASS__;
        $instance = new $class(count($array));
        $i = 0;
        foreach($array as $value) {
            $instance[$i++] = $value;
        }
        return $instance;
    }
    /**
     * Publicly accessible method for sorting the FixedArray
     * @param int|callable $dir - can be either a sort flag (SORT_ASC or SORT_DESC)
     *                            or a user-defined comparison function
     */
    function sort($dir = SORT_ASC) {
        if($dir == SORT_ASC) {
            $comp_function = function($a, $b) {
                return $a<$b;
            };
        } else if($dir == SORT_DESC) {
            $comp_function = function($a, $b) {
                return $a>$b;
            };
        } elseif(is_callable($dir)) {
            $comp_function = $dir;
        } else {
            trigger_error('Bad argument provided for sort flag. Valid parameters are '
                        . 'SORT_ASC, SORT_DESC, or a user-defined sorting function');
            //proceed as though SORT_ASC
            $comp_function = function($a, $b) {
                return $a<$b;
            };
        }
        $this->_quicksort($comp_function, 0, $this->getSize()-1);
    }
    /**
     * Finds a pivot point using a 'midpoint of three' procedure
     * @param int $left - left index
     * @param int $right - right index
     * @return array - array contains the pivot's index and its value
     */
    protected function _pivot_selection_function($left, $right) {
        $midpoint = (int)(((($right-$left)%2)==1) ? (($right-1-$left)/2 + $left) : 
                                                    (($right-$left)/2 + $left));
        if($this->offsetGet($right)<$this->offsetGet($left)) {
            if($this->offsetGet($midpoint) > $this->offsetGet($right)) {
                return array($right, $this->offsetGet($right));
            } else {
                return ($this->offsetGet($midpoint) > $this->offsetGet($left)) ? 
                                      array($midpoint, $this->offsetGet($midpoint)) : 
                                      array($left, $this->offsetGet($left));
            }
        } else {
            if($this->offsetGet($midpoint) > $this->offsetGet($left)) {
                return array($left, $this->offsetGet($left));
            } else {
                return ($this->offsetGet($midpoint) > $this->offsetGet($right)) ? 
                                      array($midpoint, $this->offsetGet($midpoint)) : 
                                      array($right, $this->offsetGet($right));
            }
        }
    }
    /**
     * Implement a recursive quicksort algorithm ordering based on the passed-in 
     * comparison function
     * @param callable $comp_function
     * @param int $left_offset
     * @param int $right_offset
     */
    protected function _quicksort($comp_function, $left_offset, $right_offset) {
        if($right_offset - $left_offset < 1) return;

        list($key, $value) = $this->_pivot_selection_function($left_offset, 
                                                                 $right_offset);
        if($key != $left_offset) {
            $this->_swap($left_offset, $key);
        }
        $j = $left_offset+1;
        $has_larger = false;
        for($i=$j; $i <= $right_offset; $i++) {
            $val = $this->offsetGet($i);
            $comp = $comp_function($val,$value);
            if($has_larger && $comp) {
                $this->_swap($j, $i);
                $j++;
            } elseif($comp) {
                $j++; //just advance pointer, no swap
            } elseif(!$has_larger) {
                $has_larger = true;
            }
        }
        $this->_swap($left_offset, $j-1);
        $this->_quicksort($comp_function, $left_offset, $j-2);
        $this->_quicksort($comp_function, $j, $right_offset);
    }

    protected function _swap($i, $j) {
        $temp = $this->offsetGet($j);
        $this->offsetSet($j, $this->offsetGet($i));
        $this->offsetSet($i, $temp);
    }
}


$M = new SortableSplFixedArray(100000);
for($i=0;$i<$count;$i++){
$M[$i]=mt_rand(1, 1000000);

}

$M ->sort(SORT_ASC);
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы