Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Сортировка в ширину (https://javascript.ru/forum/project/15633-sortirovka-v-shirinu.html)

faiwer 07.03.2011 01:11

Сортировка в ширину
 
Доброго времени суток... Приспичило меня (просто ради интереса) сравнить скорость работы сортировки в ширину с сортировкой быстрой. Причём решил сделать это в firebug-е...

Код следующий:

console.clear();

// Формирование массива

var w = 10 * 1000; // разброс значений
var h = 400 * 1000; // количество элементов
var a = new Array(h); // массив

console.time('Make array');
for( var i = 0; i < h; ++i )
{
    a[i] = Math.floor(Math.random() * w);
}
console.timeEnd('Make array');

// Cортировка "в ширину"

console.time('WideSort');
var b = new Array(w);
var c = new Array(h);

for( i = 0; i < h; ++i )
{
    if( !b[ a[i] ] )
        b[ a[i] ] = 1;
    else 
        ++b[ a[i] ];
}

var z = -1;
for( i = 0; i < w; ++i )
{
    for( var t = 0; t < b[i]; ++t )
    {
        z++;
        c[z] = i;
    }
}
console.timeEnd('WideSort');

// Быстрая сортировка

console.time('QuickSort');
function qsort( mas, f, t )
{
    var l = f, r = t;
    var middle = Math.floor( (t + f)/ 2 );
    var m = mas[ middle ];

    do {
        while( mas[l] < m ) ++l; // находим первый слева элемент больший центрального
        while( mas[r] > m ) --r; // находим первый правый элемент меньший центрального

        if( l <= r ) { // меняем местами больший чем М элемент слева, с меньшим чем М,
            var temp = mas[l]; // элементом справа
            mas[l] = mas[r];
            mas[r] = temp;
            ++l; --r;
        }
    } while ( r >= l ); // пока не кончится отрезок массива

    if( f < r ) qsort( mas, f, r );
    if( t > l ) qsort( mas, l, t );
}
qsort( a, 0, a.length - 1 );
console.timeEnd('QuickSort');


// Проверка
for( i = 0; i < h; ++i )
    if( a[i] != c[i] )
    {
        console.log('a[i] = ',a[i],' c[i] = ',c[i]);
        break;
    }


Результат ужасен, сортировка в ширину у меня всегда проигрывает, какие бы я исходные данные не ставил. Проверил тоже в Delphi, там ситуация более идеологически верная - быстрая сортировка медленнее примерно в 10 раз, вплоть до увеличения h до 2-3 миллионов.

Код:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows;

type
  ar = array of integer;
var
  v: ar;

procedure qSort(l,r:longint);
var i,j,p:longint;
    w,q:longint;
begin
  i := l; j := r;
  q := v[(l+r) div 2];

  repeat
    while (v[i] < q)
      do inc(i);
    while (q < v[j])
      do dec(j);

    if (i <= j) then
    begin
      w:=v[i]; v[i]:=v[j]; v[j]:=w;
      inc(i); dec(j);
    end;
  until (i > j);
  if (l < j) then qSort(l,j);
  if (i < r) then qSort(i,r);
end;

function wideSort( mas: ar; height: integer ): ar;
var
  c: array of integer;
  i, t, count: integer;
begin
  SetLength( c, height + 1 );

  for i:=0 to Length(mas)-1 do
    c[ mas[i] ] := c[ mas[i] ] + 1;

  SetLength( result, Length(mas) );
  count := -1;
  for i:=0 to height do
    for t := 1 to c[i] do
    begin
      inc( count );
      result[ count ] := i;
    end;

end;

const
  max = 50 * 1000 * 1000;
  height = 10;
var
  t: cardinal;
  i: longint;
  q: ar;
begin
  Setlength( v, max );
  for i:=0 to max-1 do
    v[i] := random(height - 1) + 1;

  t := getTickCount();
  q := wideSort( v, height );
  t := getTickCount() - t;
  writeLn('WideSort = ', t);

  t := getTickCount();
  qSort( 0, length(v)-1 );
  t := getTickCount() - t;
  writeLn('QSort = ', t);

  ReadLn;
end.

Можно ли в Js вернуть "справедливость"? :) Насколько я понимаю, всё дело в медленном создании массива...

P.S. Я в js совсем "зелёный" :)

#upd

Chrome:

Цитата:

Make array: 1558ms
WideSort: 3584ms
QuickSort: 444ms
:)

Gvozd 07.03.2011 04:44

Цитата:

Сообщение от faiwer
Можно ли в Js вернуть "справедливость"?

по-моему все в порядке.
Цитата:

Сообщение от faiwer
Насколько я понимаю, всё дело в медленном создании массива...

проверь фаербагом так ли это

faiwer 07.03.2011 08:56

Цитата:

по-моему все в порядке.
Что же тут нормального :) Вот нормальный результат для 50лямов в Delphi:
Цитата:

WideSort = 515
QSort = 5491
Найти причину проблемы не смог =( Кроется она в строчке после else:
for( i = 0; i < h; ++i ) 
{
    var p = a[i]; 
    if( !b[ p ] ) 
        b[ p ] = 1; 
    else 
        ++b[ p ]; 
}

Gvozd 07.03.2011 10:47

Цитата:

Сообщение от faiwer
Вот нормальный результат для 50лямов в Delphi:

это недоразумение.
связанно может быть с тем, что в Delphi слишком больше накладные расходы на вызов функции, или еще с чем-то.
Почитайте про сложность алгоритмов, и подумайте как от сложности зависит скорость. только хорошо подумайте.

PS Откуда вы взяли вообще такое дивное название "сортировка в ширину".
гугл выдает в первую очередь эту тему)
PPS *тут должно было быть что-то нехорошее про Delphi. Но может быть и ваша реклама*.

faiwer 07.03.2011 11:25

Цитата:

это недоразумение.
Это закономерность )

Цитата:

PS Откуда вы взяли вообще такое дивное название "сортировка в ширину".
Gvozd, вот - http://acmp.ru/index.asp?main=solution&id_task=41 . Называется она правда иначе (цифровая сортировка), но суть от этого не меняется. qSort-ом, насколько я помню, ту задачу не решить, по времени не укладывается :) Хотя если применить какую нидь шаманскую си магию...

Цитата:

Почитайте про сложность алгоритмов, и подумайте как от сложности зависит скорость. только хорошо подумайте.
Вы про это?
Цитата:

Данный алгоритм имеет порядок сложности O(N)
Я полагаю, что сложность там не O(N), а более запутанная, и выводить мне её лень, никогда эти О() не любил...

Kolyaj 07.03.2011 12:17

Запустил ваш пример (Firefox 3.6)
Цитата:

Make array: 131ms
WideSort: 215ms
QuickSort: 1031ms

faiwer 07.03.2011 13:30

Kolyaj, о_О... unix-версия? У меня 3.6.15 (win32) выдаёт:

Цитата:

Make array: 1072ms
WideSort: 2416ms
QuickSort: 1830ms

Kolyaj 07.03.2011 14:39

WinXP.

В коде из первого сообщения ничего не менял.


Часовой пояс GMT +3, время: 07:40.