Векторная сортировка ActionScript 3 внезапно стала очень медленной?

#flash #actionscript-3 #sorting

#flash #actionscript-3 #сортировка

Вопрос:

Во время игры с as’vector.sort() Я обнаружил, что он ведет себя нормально во всех случаях, за исключением случаев, когда ему необходимо отсортировать вектор только с 2 или 3 отличительными значениями. Если это так, функция sort() выполняется очень медленно. Вот мой код:

 var test:Vector.<int>=new Vector.<int>  ;
for (var i:int=0; i<6000; i  ) {
    test.push(Math.floor(Math.random()*2));
}
var timer:Number
var timer2:Number
timer=new Date().getTime();
test.sort(compare)
timer2=new Date().getTime();
trace(timer2-timer)
function compare(x:int,y:int):Number {
    if (x>y) {
        return 1;
    } else if (x<y) {
        return -1;
    } else {
        return 0;
    }
}
  

просто скопируйте этот код.
В чем может быть проблема?
Спасибо.

Ответ №1:

Я только что столкнулся с такой же проблемой: Vector.sort () из 50 000 объектов значений в поле с тремя различными значениями: ~ 2 минуты. Затем я вызываю почти точно такую же сортировку, с той лишь разницей, что я разрываю связь (когда x == y) для вторичного поля с уникальным значением (то есть для поля с 50 000 различными значениями): менее 1 секунды! Вот код функции сортировки, чтобы проиллюстрировать, что я имею в виду:

 private function vastlyImprovedVectorSortFunc(x:MyVO, y:MyVO):Number
{
    if(x.fieldWithThreeValues > y.fieldWithThreeValues)
        return 1;
    else
        if(x.fieldWithThreeValues < y.fieldWithThreeValues )
            return -1;
        else
            if(x.uniqueFieldWithManyValues > y.uniqueFieldWithManyValues)
                return 1;
            else
                if(x.uniqueFieldWithManyValues < y.uniqueFieldWithManyValues )
                    return -1;
                else
                    return 0;
}
  

Странный мир, верно ?! Похоже, я прошу функцию выполнить намного больше работы, применяя вторичную сортировку к очень уникальному полю, но, по-видимому, производительность функции сортировки вектора ухудшается из-за меньшего количества отдельных сортировочных «ячеек» для размещения вещей. Я обнаружил это, когда сортировал свой вектор по полю с двадцатью значениями, и производительность по-прежнему оставалась плохой (~ 20 секунд), но значительно улучшилась. Тогда это было еще лучше для поля с примерно сотыми значениями; поэтому я подумал, почему бы не пойти полным ходом и просто выполнить окончательную сортировку по (уникальному) первичному ключу.

Для меня это меняет правила игры! Надеюсь, это поможет кому-то еще. Удивлен, что этого нет где-то в документах.

Ответ №2:

На самом деле это не происходит с 2 или 3 значениями, точнее, эффект тем заметнее, чем меньше различных значений в векторе. У каждого алгоритма сортировки есть свои плюсы и минусы. Встроенный (я считаю, что это пузырьковая сортировка) будет работать почти в худшем случае, когда есть несколько различных значений. Вы могли бы попробовать эту простую альтернативу (сортировку по основанию), но обратите внимание, что она будет занимать больший объем памяти, и чем больше, тем больше различных значений в векторе.

 package examples 
{
import flash.display.Sprite;

/**
 * An example for stackoverflow.com
 * @author wvxvw
 */
public class KindOfRadixSort extends Sprite
{

    public function KindOfRadixSort() 
    {
        super();
        this.test();
    }

    private function test():void
    {
        var test:Vector.<int> = new <int>[];
        var timer:Number;
        var timer2:Number;

        for (var i:int; i < 6000; i  ) test.push(Math.random() * 5);

        timer = new Date().getTime();
        test.sort(compare);
        timer2 = new Date().getTime();
        trace(timer2 - timer); // 2488

        timer = new Date().getTime();
        this.kindOfRadixSort(test);
        timer2 = new Date().getTime();
        trace(timer2 - timer); // 3
    }

    private function compare(x:int, y:int):int
    {
        var result:int;
        if (x > y) result = 1;
        else if (x < y) result = -1;
        return resu<
    }

    private function kindOfRadixSort(vector:Vector.<int>):Vector.<int>
    {
        // Arrays are sparse, therefore we don't allocate memory when having
        // gaps between filled indices as we would have we used vector.
        var cache:Array = [];
        var result:Vector.<int> = new <int>[];
        var i:int;

        for each (i in vector)
        {
            if (cache[i]) (cache[i] as Vector.<int>).push(i);
            else cache[i] = new <int>[i];
        }
        // A for-each loop could be better here, and, in fact, for-each on
        // arrays usually provides elements in order 0..length, however,
        // the specs say the order is undefined.
        for (i = cache.length - 1; i >= 0; i--)
        {
            if (cache[i] is Vector.<int>)
                result = (cache[i] as Vector.<int>).concat(result);
        }
        return resu<
    }
}
}